unexist.dev

Changeset 233:5b05066b8c21

Split test.rs into several test cases
author unexist
date Mon, 30 Nov 2020 14:56:16 +0100
parents cdfe2417dd14
children fe7e42792d63
files rubtle-lib/src/tests/mod.rs rubtle-lib/src/tests/rubtle.rs rubtle-lib/src/tests/rubtle/array.rs rubtle-lib/src/tests/rubtle/basic.rs rubtle-lib/src/tests/rubtle/eval.rs rubtle-lib/src/tests/rubtle/function.rs rubtle-lib/src/tests/rubtle/helper.rs rubtle-lib/src/tests/rubtle/mod.rs rubtle-lib/src/tests/rubtle/object.rs rubtle-lib/src/tests/rubtle/object_builder.rs rubtle/src/main.rs
diffstat 11 files changed, 833 insertions(+), 762 deletions(-) [+]
line wrap: on
line diff
--- a/rubtle-lib/src/tests/mod.rs	Mon Nov 30 13:34:30 2020 +0100
+++ b/rubtle-lib/src/tests/mod.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -1,3 +1,3 @@
 mod object_builder;
 mod rubtle;
-mod value;
+mod value;
\ No newline at end of file
--- a/rubtle-lib/src/tests/rubtle.rs	Mon Nov 30 13:34:30 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,761 +0,0 @@
-///
-/// @package Rubtle-Lib
-///
-/// @file Rubtle tests
-/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
-/// @version $Id$
-///
-/// This program can be distributed under the terms of the GNU GPLv2.
-/// See the file LICENSE for details.
-///
-use crate::{Invocation, ObjectBuilder, Rubtle, Value};
-use crate::types::CallbackResult;
-
-use std::collections::HashMap;
-
-///
-/// Helper functions
-///
-
-fn js_printer(inv: Invocation<i8>) -> CallbackResult<Value> {
-    let args = inv.args.unwrap();
-
-    for val in args.iter() {
-        match val.coerce_string() {
-            Some(s) => println!("{:?}", s),
-            None => eprintln!("Error unwrap value"),
-        }
-    }
-
-    Ok(Value::from(true))
-}
-
-fn js_assert(inv: Invocation<i8>) -> CallbackResult<Value> {
-    let args = inv.args.unwrap();
-    let assert_val = args.first().unwrap().as_boolean().unwrap();
-    let assert_mesg = args.last().unwrap().coerce_string().unwrap();
-
-    assert_eq!(true, assert_val, "{}", assert_mesg);
-
-    /* Make compiler happy */
-    Ok(Value::from(true))
-}
-
-///
-/// Stack primitives
-///
-
-#[test]
-fn push_and_pop_bool_value() {
-    let rubtle = Rubtle::new();
-
-    let rval = Value::from(true);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn push_and_pop_number_value() {
-    let rubtle = Rubtle::new();
-
-    let rval = Value::from(4);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn push_and_pop_string_value() {
-    let rubtle = Rubtle::new();
-
-    let rval = Value::from("rubtle");
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn push_and_pop_none_value() {
-    let rubtle = Rubtle::new();
-
-    let rval = Value::from(());
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-///
-/// Stack arrays
-///
-
-#[test]
-fn push_and_pop_array_value_i32() {
-    let rubtle = Rubtle::new();
-
-    let ary: Vec<i32> = vec![1, 2];
-    let rval = Value::from(&ary);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn push_and_pop_array_value_f64() {
-    let rubtle = Rubtle::new();
-
-    let ary: Vec<f64> = vec![1.0, 2.0];
-    let rval = Value::from(&ary);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn push_and_pop_array_value_bool() {
-    let rubtle = Rubtle::new();
-
-    let ary: Vec<bool> = vec![true, false];
-    let rval = Value::from(&ary);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-///
-/// Stack objects
-///
-
-#[test]
-fn push_and_pop_object_i32() {
-    let rubtle = Rubtle::new();
-
-    let mut hash: HashMap<&str, i32> = HashMap::new();
-
-    hash.insert("rubtle", 1);
-    hash.insert("rubtle", 2);
-
-    let rval = Value::from(&hash);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn push_and_pop_object_f64() {
-    let rubtle = Rubtle::new();
-
-    let mut hash: HashMap<&str, f64> = HashMap::new();
-
-    hash.insert("rubtle", 1.0);
-    hash.insert("rubtle", 2.0);
-
-    let rval = Value::from(&hash);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn push_and_pop_object_bool() {
-    let rubtle = Rubtle::new();
-
-    let mut hash: HashMap<&str, bool> = HashMap::new();
-
-    hash.insert("rubtle", true);
-    hash.insert("rubtle", false);
-
-    let rval = Value::from(&hash);
-
-    rubtle.push_value(&rval);
-    let rval2 = rubtle.pop_value().unwrap();
-
-    assert_eq!(rval, rval2);
-}
-
-///
-/// Eval
-///
-
-#[test]
-fn evil_eval_test() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = 'rubtle';
-    "#,
-    );
-}
-
-///
-/// Global
-///
-
-#[test]
-fn set_global_bool_value() {
-    let rubtle = Rubtle::new();
-    let rval = Value::from(true);
-
-    rubtle.set_global_value("rubtle", &rval);
-}
-
-#[test]
-fn set_global_number_value() {
-    let rubtle = Rubtle::new();
-    let rval = Value::from(4);
-
-    rubtle.set_global_value("rubtle", &rval);
-}
-
-#[test]
-fn set_global_string_value() {
-    let rubtle = Rubtle::new();
-    let rval = Value::from("rubtle");
-
-    rubtle.set_global_value("rubtle", &rval);
-}
-
-#[test]
-fn get_global_bool_value() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = true;
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-    let rval2 = Value::from(true);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_number_value_i32() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = 4;
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-    let rval2 = Value::from(4);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_number_value_f64() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = 4.0;
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-    let rval2 = Value::from(4.0);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_string_value() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = 'test';
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-    let rval2 = Value::from("test");
-
-    assert_eq!(rval, rval2);
-}
-
-///
-/// Global arrays
-///
-
-#[test]
-fn get_global_array_value_bool() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = [true, false];
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let vec = vec![true, false];
-    let rval2 = Value::from(&vec);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_array_value_i32() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = [1, 2];
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let vec = vec![1, 2];
-    let rval2 = Value::from(&vec);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_array_value_f64() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = [1.0, 2.0];
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let vec = vec![1.0, 2.0];
-    let rval2 = Value::from(&vec);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_array_value_str() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = ["rubtle", "rubtle"];
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let vec = vec!["rubtle", "rubtle"];
-    let rval2 = Value::from(&vec);
-
-    assert_eq!(rval, rval2);
-}
-
-///
-/// Global arrays
-///
-
-#[test]
-fn get_global_object_value_bool() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = { "rubtle1": true, "rubtle2": false };
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let mut hash: HashMap<&str, bool> = HashMap::new();
-
-    hash.insert("rubtle1", true);
-    hash.insert("rubtle2", false);
-
-    let rval2 = Value::from(&hash);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_object_value_i32() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = { "rubtle1": 1, "rubtle2": 2 };
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let mut hash: HashMap<&str, i32> = HashMap::new();
-
-    hash.insert("rubtle1", 1);
-    hash.insert("rubtle2", 2);
-
-    let rval2 = Value::from(&hash);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_object_value_f64() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = { "rubtle1": 1.0, "rubtle2": 2.0 };
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let mut hash: HashMap<&str, f64> = HashMap::new();
-
-    hash.insert("rubtle1", 1.0);
-    hash.insert("rubtle2", 2.0);
-
-    let rval2 = Value::from(&hash);
-
-    assert_eq!(rval, rval2);
-}
-
-#[test]
-fn get_global_object_value_str() {
-    let rubtle = Rubtle::new();
-
-    rubtle.eval(
-        r#"
-        var rubtle = { "rubtle1": "rubtle", "rubtle2": "rubtle" };
-    "#,
-    );
-
-    let rval = rubtle.get_global_value("rubtle").unwrap();
-
-    let mut hash: HashMap<&str, &str> = HashMap::new();
-
-    hash.insert("rubtle1", "rubtle");
-    hash.insert("rubtle2", "rubtle");
-
-    let rval2 = Value::from(&hash);
-
-    assert_eq!(rval, rval2);
-}
-
-///
-/// Global functions
-///
-
-#[test]
-fn set_global_function_as_closure() {
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_function("square", |inv| -> CallbackResult<Value> {
-        let args = inv.args.unwrap();
-
-        let i = args.first().unwrap().as_number().unwrap();
-
-        Ok(Value::from(i * i))
-    });
-}
-
-#[test]
-fn set_and_run_global_printer() {
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_function("print", js_printer);
-
-    rubtle.eval(
-        r#"
-        print('Test');
-    "#,
-    );
-}
-
-///
-/// Global objects
-///
-
-#[test]
-fn set_global_object_with_ctor() {
-    #[derive(Default)]
-    struct UserData {
-        value: i32,
-    };
-
-    let mut object = ObjectBuilder::<UserData>::new()
-        .with_constructor(|inv| {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value = 1;
-        })
-        .build();
-
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_object("Counter", &mut object);
-
-    rubtle.set_global_function("assert", js_assert);
-
-    rubtle.eval(
-        r#"
-        var counter = new Counter();
-
-        assert(typeof counter != 'undefined', "Damn!");
-    "#,
-    );
-}
-
-#[test]
-fn set_global_object_with_ctor_and_method() {
-    #[derive(Default)]
-    struct UserData {
-        value: i32,
-    };
-
-    let mut object = ObjectBuilder::<UserData>::new()
-        .with_constructor(|inv| {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value = 1;
-        })
-        .with_method("inc", |inv| -> CallbackResult<Value> {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value += 1;
-
-            Ok(Value::from(udata.value))
-        })
-        .build();
-
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_object("Counter", &mut object);
-
-    rubtle.set_global_function("assert", js_assert);
-
-    rubtle.eval(
-        r#"
-        var counter = new Counter();
-
-        assert(typeof counter != 'undefined', "Damn!");
-
-        counter.inc();
-    "#,
-    );
-}
-
-#[test]
-fn set_global_object_with_ctor_and_methods() {
-    #[derive(Default)]
-    struct UserData {
-        value: i32,
-    };
-
-    let mut object = ObjectBuilder::<UserData>::new()
-        .with_constructor(|inv| {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value = 1;
-        })
-        .with_method("inc", |inv| -> CallbackResult<Value> {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value += 1;
-
-            Ok(Value::from(udata.value))
-        })
-        .with_method("print", |inv| -> CallbackResult<Value> {
-            let udata = inv.udata.as_ref().unwrap();
-
-            println!("Value={}", udata.value);
-
-            Ok(Value::from(udata.value))
-        })
-        .build();
-
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_object("Counter", &mut object);
-
-    rubtle.set_global_function("assert", js_assert);
-
-    rubtle.eval(
-        r#"
-        var counter = new Counter();
-
-        assert(typeof counter != 'undefined', "Damn!");
-
-        counter.inc();
-        var value = counter.inc();
-
-        assert(3 == value, "Damn!");
-
-        counter.print();
-    "#,
-    );
-}
-
-#[test]
-fn set_global_object_with_ctor_and_method_with_return_value() {
-    #[derive(Default)]
-    struct UserData {
-        value: i32,
-    };
-
-    let mut object = ObjectBuilder::<UserData>::new()
-        .with_constructor(|inv| {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value = 1;
-        })
-        .with_method("inc", |inv| -> CallbackResult<Value> {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value += 1;
-
-            Ok(Value::from(udata.value))
-        })
-        .build();
-
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_object("Counter", &mut object);
-
-    rubtle.set_global_function("print", js_printer);
-    rubtle.set_global_function("assert", js_assert);
-
-    rubtle.eval(
-        r#"
-        var counter = new Counter();
-
-        assert(typeof counter != 'undefined', "Damn!");
-
-        counter.inc();
-
-        var value = counter.inc();
-
-        print(value);
-
-        assert(3 == value, "Damn!");
-    "#,
-    );
-}
-
-#[test]
-fn set_global_object_with_ctor_with_arguments_and_method_with_return_value() {
-    #[derive(Default)]
-    struct UserData {
-        value: i32,
-    };
-
-    let mut object = ObjectBuilder::<UserData>::new()
-        .with_constructor(|inv| {
-            let mut udata = inv.udata.as_mut().unwrap();
-            let args = inv.args.as_ref().unwrap();
-
-            match args.first() {
-                Some(val) => udata.value = val.as_number().unwrap() as i32,
-                None => udata.value = 1,
-            }
-        })
-        .with_method("inc", |inv| -> CallbackResult<Value> {
-            let mut udata = inv.udata.as_mut().unwrap();
-
-            udata.value += 1;
-
-            Ok(Value::from(udata.value))
-        })
-        .build();
-
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_object("Counter", &mut object);
-
-    rubtle.set_global_function("assert", js_assert);
-
-    rubtle.eval(
-        r#"
-        var counter = new Counter(5);
-
-        assert(typeof counter != 'undefined', "Damn!");
-
-        var value = counter.inc();
-
-        assert(6 == value, "Damn!");
-    "#,
-    );
-}
-
-#[test]
-fn set_global_object_with_ctor_with_arguments_and_method_with_arguments_and_return_value() {
-    #[derive(Default)]
-    struct UserData {
-        value: i32,
-    };
-
-    let mut object = ObjectBuilder::<UserData>::new()
-        .with_constructor(|inv| {
-            let mut udata = inv.udata.as_mut().unwrap();
-            let args = inv.args.as_ref().unwrap();
-
-            match args.first() {
-                Some(val) => udata.value = val.as_number().unwrap() as i32,
-                None => udata.value = 1,
-            }
-        })
-        .with_method("inc", |inv| -> CallbackResult<Value> {
-            let mut udata = inv.udata.as_mut().unwrap();
-            let args = inv.args.as_ref().unwrap();
-
-            match args.first() {
-                Some(val) => udata.value += val.as_number().unwrap() as i32,
-                None => udata.value += 1,
-            }
-
-            Ok(Value::from(udata.value))
-        })
-        .build();
-
-    let rubtle = Rubtle::new();
-
-    rubtle.set_global_object("Counter", &mut object);
-
-    rubtle.set_global_function("assert", js_assert);
-
-    rubtle.eval(
-        r#"
-        var counter = new Counter(2);
-
-        assert(typeof counter != 'undefined', "Damn!");
-
-        var value = counter.inc(8);
-
-        assert(10 == value, "Damn!");
-    "#,
-    );
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/array.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,130 @@
+///
+/// @package Rubtle-Lib
+///
+/// @file Rubtle tests - arrays
+/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
+/// @version $Id$
+///
+/// This program can be distributed under the terms of the GNU GPLv2.
+/// See the file LICENSE for details.
+///
+use crate::{Rubtle, Value};
+
+///
+/// Stack arrays
+///
+
+#[test]
+fn push_and_pop_array_value_i32() {
+    let rubtle = Rubtle::new();
+
+    let ary: Vec<i32> = vec![1, 2];
+    let rval = Value::from(&ary);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn push_and_pop_array_value_f64() {
+    let rubtle = Rubtle::new();
+
+    let ary: Vec<f64> = vec![1.0, 2.0];
+    let rval = Value::from(&ary);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn push_and_pop_array_value_bool() {
+    let rubtle = Rubtle::new();
+
+    let ary: Vec<bool> = vec![true, false];
+    let rval = Value::from(&ary);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+///
+/// Global arrays
+///
+
+#[test]
+fn get_global_array_value_bool() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = [true, false];
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let vec = vec![true, false];
+    let rval2 = Value::from(&vec);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_array_value_i32() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = [1, 2];
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let vec = vec![1, 2];
+    let rval2 = Value::from(&vec);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_array_value_f64() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = [1.0, 2.0];
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let vec = vec![1.0, 2.0];
+    let rval2 = Value::from(&vec);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_array_value_str() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = ["rubtle", "rubtle"];
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let vec = vec!["rubtle", "rubtle"];
+    let rval2 = Value::from(&vec);
+
+    assert_eq!(rval, rval2);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/basic.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,155 @@
+///
+/// @package Rubtle-Lib
+///
+/// @file Rubtle tests - basic
+/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
+/// @version $Id$
+///
+/// This program can be distributed under the terms of the GNU GPLv2.
+/// See the file LICENSE for details.
+///
+use crate::{Rubtle, Value};
+
+///
+/// Stack primitives
+///
+
+#[test]
+fn push_and_pop_bool_value() {
+    let rubtle = Rubtle::new();
+
+    let rval = Value::from(true);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn push_and_pop_number_value() {
+    let rubtle = Rubtle::new();
+
+    let rval = Value::from(4);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn push_and_pop_string_value() {
+    let rubtle = Rubtle::new();
+
+    let rval = Value::from("rubtle");
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn push_and_pop_none_value() {
+    let rubtle = Rubtle::new();
+
+    let rval = Value::from(());
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+///
+/// Global
+///
+
+#[test]
+fn set_global_bool_value() {
+    let rubtle = Rubtle::new();
+    let rval = Value::from(true);
+
+    rubtle.set_global_value("rubtle", &rval);
+}
+
+#[test]
+fn set_global_number_value() {
+    let rubtle = Rubtle::new();
+    let rval = Value::from(4);
+
+    rubtle.set_global_value("rubtle", &rval);
+}
+
+#[test]
+fn set_global_string_value() {
+    let rubtle = Rubtle::new();
+    let rval = Value::from("rubtle");
+
+    rubtle.set_global_value("rubtle", &rval);
+}
+
+#[test]
+fn get_global_bool_value() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = true;
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+    let rval2 = Value::from(true);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_number_value_i32() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = 4;
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+    let rval2 = Value::from(4);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_number_value_f64() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = 4.0;
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+    let rval2 = Value::from(4.0);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_string_value() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = 'test';
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+    let rval2 = Value::from("test");
+
+    assert_eq!(rval, rval2);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/eval.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,26 @@
+///
+/// @package Rubtle-Lib
+///
+/// @file Rubtle tests - eval
+/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
+/// @version $Id$
+///
+/// This program can be distributed under the terms of the GNU GPLv2.
+/// See the file LICENSE for details.
+///
+use crate::Rubtle;
+
+///
+/// Eval
+///
+
+#[test]
+fn evil_eval_test() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = 'rubtle';
+    "#,
+    );
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/function.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,43 @@
+///
+/// @package Rubtle-Lib
+///
+/// @file Rubtle tests - function
+/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
+/// @version $Id$
+///
+/// This program can be distributed under the terms of the GNU GPLv2.
+/// See the file LICENSE for details.
+///
+use crate::{Rubtle, Value, CallbackResult};
+
+use crate::tests::rubtle::helper::js_printer;
+
+///
+/// Global functions
+///
+
+#[test]
+fn set_global_function_as_closure() {
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_function("square", |inv| -> CallbackResult<Value> {
+        let args = inv.args.unwrap();
+
+        let i = args.first().unwrap().as_number().unwrap();
+
+        Ok(Value::from(i * i))
+    });
+}
+
+#[test]
+fn set_and_run_global_printer() {
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_function("print", js_printer);
+
+    rubtle.eval(
+        r#"
+        print('Test');
+    "#,
+    );
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/helper.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,39 @@
+///
+/// @package Rubtle-Lib
+///
+/// @file Rubtle tests - helper
+/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
+/// @version $Id$
+///
+/// This program can be distributed under the terms of the GNU GPLv2.
+/// See the file LICENSE for details.
+///
+use crate::{Invocation, CallbackResult, Value};
+
+///
+/// Helper functions
+///
+
+pub fn js_printer(inv: Invocation<i8>) -> CallbackResult<Value> {
+    let args = inv.args.unwrap();
+
+    for val in args.iter() {
+        match val.coerce_string() {
+            Some(s) => println!("{:?}", s),
+            None => eprintln!("Error unwrap value"),
+        }
+    }
+
+    Ok(Value::from(true))
+}
+
+pub fn js_assert(inv: Invocation<i8>) -> CallbackResult<Value> {
+    let args = inv.args.unwrap();
+    let assert_val = args.first().unwrap().as_boolean().unwrap();
+    let assert_mesg = args.last().unwrap().coerce_string().unwrap();
+
+    assert_eq!(true, assert_val, "{}", assert_mesg);
+
+    /* Make compiler happy */
+    Ok(Value::from(true))
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/mod.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,7 @@
+mod array;
+mod basic;
+mod eval;
+mod function;
+mod helper;
+mod object;
+mod object_builder;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/object.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,160 @@
+///
+/// @package Rubtle-Lib
+///
+/// @file Rubtle tests - objects
+/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
+/// @version $Id$
+///
+/// This program can be distributed under the terms of the GNU GPLv2.
+/// See the file LICENSE for details.
+///
+use crate::{Rubtle, Value};
+
+use std::collections::HashMap;
+
+///
+/// Stack objects
+///
+
+#[test]
+fn push_and_pop_object_i32() {
+    let rubtle = Rubtle::new();
+
+    let mut hash: HashMap<&str, i32> = HashMap::new();
+
+    hash.insert("rubtle", 1);
+    hash.insert("rubtle", 2);
+
+    let rval = Value::from(&hash);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn push_and_pop_object_f64() {
+    let rubtle = Rubtle::new();
+
+    let mut hash: HashMap<&str, f64> = HashMap::new();
+
+    hash.insert("rubtle", 1.0);
+    hash.insert("rubtle", 2.0);
+
+    let rval = Value::from(&hash);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn push_and_pop_object_bool() {
+    let rubtle = Rubtle::new();
+
+    let mut hash: HashMap<&str, bool> = HashMap::new();
+
+    hash.insert("rubtle", true);
+    hash.insert("rubtle", false);
+
+    let rval = Value::from(&hash);
+
+    rubtle.push_value(&rval);
+    let rval2 = rubtle.pop_value().unwrap();
+
+    assert_eq!(rval, rval2);
+}
+
+///
+/// Global objects
+///
+
+#[test]
+fn get_global_object_value_bool() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = { "rubtle1": true, "rubtle2": false };
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let mut hash: HashMap<&str, bool> = HashMap::new();
+
+    hash.insert("rubtle1", true);
+    hash.insert("rubtle2", false);
+
+    let rval2 = Value::from(&hash);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_object_value_i32() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = { "rubtle1": 1, "rubtle2": 2 };
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let mut hash: HashMap<&str, i32> = HashMap::new();
+
+    hash.insert("rubtle1", 1);
+    hash.insert("rubtle2", 2);
+
+    let rval2 = Value::from(&hash);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_object_value_f64() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = { "rubtle1": 1.0, "rubtle2": 2.0 };
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let mut hash: HashMap<&str, f64> = HashMap::new();
+
+    hash.insert("rubtle1", 1.0);
+    hash.insert("rubtle2", 2.0);
+
+    let rval2 = Value::from(&hash);
+
+    assert_eq!(rval, rval2);
+}
+
+#[test]
+fn get_global_object_value_str() {
+    let rubtle = Rubtle::new();
+
+    rubtle.eval(
+        r#"
+        var rubtle = { "rubtle1": "rubtle", "rubtle2": "rubtle" };
+    "#,
+    );
+
+    let rval = rubtle.get_global_value("rubtle").unwrap();
+
+    let mut hash: HashMap<&str, &str> = HashMap::new();
+
+    hash.insert("rubtle1", "rubtle");
+    hash.insert("rubtle2", "rubtle");
+
+    let rval2 = Value::from(&hash);
+
+    assert_eq!(rval, rval2);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rubtle-lib/src/tests/rubtle/object_builder.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -0,0 +1,260 @@
+///
+/// @package Rubtle-Lib
+///
+/// @file Rubtle tests - basic
+/// @copyright 2020 Christoph Kappel <christoph@unexist.dev>
+/// @version $Id$
+///
+/// This program can be distributed under the terms of the GNU GPLv2.
+/// See the file LICENSE for details.
+///
+use crate::{Rubtle, Value, CallbackResult, ObjectBuilder};
+
+use crate::tests::rubtle::helper::js_assert;
+use crate::tests::rubtle::helper::js_printer;
+
+///
+/// Global objects
+///
+
+#[test]
+fn set_global_object_with_ctor() {
+    #[derive(Default)]
+    struct UserData {
+        value: i32,
+    };
+
+    let mut object = ObjectBuilder::<UserData>::new()
+        .with_constructor(|inv| {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value = 1;
+        })
+        .build();
+
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_object("Counter", &mut object);
+
+    rubtle.set_global_function("assert", js_assert);
+
+    rubtle.eval(
+        r#"
+        var counter = new Counter();
+        assert(typeof counter != 'undefined', "Damn!");
+    "#,
+    );
+}
+
+#[test]
+fn set_global_object_with_ctor_and_method() {
+    #[derive(Default)]
+    struct UserData {
+        value: i32,
+    };
+
+    let mut object = ObjectBuilder::<UserData>::new()
+        .with_constructor(|inv| {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value = 1;
+        })
+        .with_method("inc", |inv| -> CallbackResult<Value> {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value += 1;
+
+            Ok(Value::from(udata.value))
+        })
+        .build();
+
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_object("Counter", &mut object);
+
+    rubtle.set_global_function("assert", js_assert);
+
+    rubtle.eval(
+        r#"
+        var counter = new Counter();
+        assert(typeof counter != 'undefined', "Damn!");
+        counter.inc();
+    "#,
+    );
+}
+
+#[test]
+fn set_global_object_with_ctor_and_methods() {
+    #[derive(Default)]
+    struct UserData {
+        value: i32,
+    };
+
+    let mut object = ObjectBuilder::<UserData>::new()
+        .with_constructor(|inv| {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value = 1;
+        })
+        .with_method("inc", |inv| -> CallbackResult<Value> {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value += 1;
+
+            Ok(Value::from(udata.value))
+        })
+        .with_method("print", |inv| -> CallbackResult<Value> {
+            let udata = inv.udata.as_ref().unwrap();
+
+            println!("Value={}", udata.value);
+
+            Ok(Value::from(udata.value))
+        })
+        .build();
+
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_object("Counter", &mut object);
+
+    rubtle.set_global_function("assert", js_assert);
+
+    rubtle.eval(
+        r#"
+        var counter = new Counter();
+        assert(typeof counter != 'undefined', "Damn!");
+        counter.inc();
+        var value = counter.inc();
+        assert(3 == value, "Damn!");
+        counter.print();
+    "#,
+    );
+}
+
+#[test]
+fn set_global_object_with_ctor_and_method_with_return_value() {
+    #[derive(Default)]
+    struct UserData {
+        value: i32,
+    };
+
+    let mut object = ObjectBuilder::<UserData>::new()
+        .with_constructor(|inv| {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value = 1;
+        })
+        .with_method("inc", |inv| -> CallbackResult<Value> {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value += 1;
+
+            Ok(Value::from(udata.value))
+        })
+        .build();
+
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_object("Counter", &mut object);
+
+    rubtle.set_global_function("print", js_printer);
+    rubtle.set_global_function("assert", js_assert);
+
+    rubtle.eval(
+        r#"
+        var counter = new Counter();
+        assert(typeof counter != 'undefined', "Damn!");
+        counter.inc();
+        var value = counter.inc();
+        print(value);
+        assert(3 == value, "Damn!");
+    "#,
+    );
+}
+
+#[test]
+fn set_global_object_with_ctor_with_arguments_and_method_with_return_value() {
+    #[derive(Default)]
+    struct UserData {
+        value: i32,
+    };
+
+    let mut object = ObjectBuilder::<UserData>::new()
+        .with_constructor(|inv| {
+            let mut udata = inv.udata.as_mut().unwrap();
+            let args = inv.args.as_ref().unwrap();
+
+            match args.first() {
+                Some(val) => udata.value = val.as_number().unwrap() as i32,
+                None => udata.value = 1,
+            }
+        })
+        .with_method("inc", |inv| -> CallbackResult<Value> {
+            let mut udata = inv.udata.as_mut().unwrap();
+
+            udata.value += 1;
+
+            Ok(Value::from(udata.value))
+        })
+        .build();
+
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_object("Counter", &mut object);
+
+    rubtle.set_global_function("assert", js_assert);
+
+    rubtle.eval(
+        r#"
+        var counter = new Counter(5);
+        assert(typeof counter != 'undefined', "Damn!");
+        var value = counter.inc();
+        assert(6 == value, "Damn!");
+    "#,
+    );
+}
+
+#[test]
+fn set_global_object_with_ctor_with_arguments_and_method_with_arguments_and_return_value() {
+    #[derive(Default)]
+    struct UserData {
+        value: i32,
+    };
+
+    let mut object = ObjectBuilder::<UserData>::new()
+        .with_constructor(|inv| {
+            let mut udata = inv.udata.as_mut().unwrap();
+            let args = inv.args.as_ref().unwrap();
+
+            match args.first() {
+                Some(val) => udata.value = val.as_number().unwrap() as i32,
+                None => udata.value = 1,
+            }
+        })
+        .with_method("inc", |inv| -> CallbackResult<Value> {
+            let mut udata = inv.udata.as_mut().unwrap();
+            let args = inv.args.as_ref().unwrap();
+
+            match args.first() {
+                Some(val) => udata.value += val.as_number().unwrap() as i32,
+                None => udata.value += 1,
+            }
+
+            Ok(Value::from(udata.value))
+        })
+        .build();
+
+    let rubtle = Rubtle::new();
+
+    rubtle.set_global_object("Counter", &mut object);
+
+    rubtle.set_global_function("assert", js_assert);
+
+    rubtle.eval(
+        r#"
+        var counter = new Counter(2);
+        assert(typeof counter != 'undefined', "Damn!");
+        var value = counter.inc(8);
+        assert(10 == value, "Damn!");
+    "#,
+    );
+}
\ No newline at end of file
--- a/rubtle/src/main.rs	Mon Nov 30 13:34:30 2020 +0100
+++ b/rubtle/src/main.rs	Mon Nov 30 14:56:16 2020 +0100
@@ -14,6 +14,10 @@
 
 use std::{env, fs};
 
+///
+/// Helper
+///
+
 fn js_printer(inv: Invocation<i8>) -> CallbackResult<Value> {
     let args = inv.args.unwrap();
 
@@ -39,6 +43,10 @@
     Ok(Value::from(true))
 }
 
+///
+/// Init
+///
+
 fn init_global(rubtle: &Rubtle) {
     rubtle.set_global_function("print", js_printer);
     rubtle.set_global_function("assert", js_assert_eq);
@@ -84,6 +92,10 @@
     rubtle.set_global_object("Rubtle", &mut object);
 }
 
+///
+/// Main
+///
+
 fn main() {
     let args: Vec<String> = env::args().collect();