From 4b9dde655e8df12434cc28078f915a03584c418a Mon Sep 17 00:00:00 2001 From: librelois <elois@ifee.fr> Date: Mon, 23 Apr 2018 17:45:33 +0200 Subject: [PATCH] [enh] add all wotb methods and all js tests (except io file) --- lib/index.js | 44 +++++--- native/Cargo.lock | 6 +- native/Cargo.toml | 2 +- native/src/lib.rs | 129 +++++++++++++++++++----- package.json | 2 +- tests/test.js | 251 +++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 384 insertions(+), 50 deletions(-) diff --git a/lib/index.js b/lib/index.js index ba91367..d096f0c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -63,25 +63,19 @@ const WotB = { }, getEnabled: function() { - var wot_size = addon.get_wot_size(this.instanceID); - var enabled_array = new Array(); - for (let i = 0; i < wot_size; i++) { - if (addon.is_enabled(this.instanceID, i)) { - enabled_array.push(i); - } - } - return enabled_array; + return addon.get_enabled(this.instanceID); }, getDisabled: function() { - var wot_size = addon.get_wot_size(this.instanceID); - var enabled_array = new Array(); - for (let i = 0; i < wot_size; i++) { - if (!addon.is_enabled(this.instanceID, i)) { - enabled_array.push(i); - } - } - return enabled_array; + return addon.get_disabled(this.instanceID); + }, + + getSentries: function(sentry_requirement) { + return addon.get_sentries(this.instanceID, sentry_requirement); + }, + + getNonSentries: function(sentry_requirement) { + return addon.get_non_sentries(this.instanceID, sentry_requirement); }, existsLink: function(source, target) { @@ -118,6 +112,24 @@ const WotB = { return distance_result.outdistanced; }, + detailedDistance: function(node, sentry_requirement, step_max, x_percent) { + var distance_result = addon.compute_distance(this.instanceID, node, sentry_requirement, step_max, x_percent); + return { + nbReached: distance_result.reached, + nbSuccess: distance_result.success, + nbSentries: distance_result.sentries, + isOutdistanced: distance_result.outdistanced + }; + }, + + detailedDistanceV2: function(node, sentry_requirement, step_max, x_percent) { + return addon.compute_distance(this.instanceID, node, sentry_requirement, step_max, x_percent); + }, + + getPaths: function(from, to, step_max) { + return addon.find_paths(this.instanceID, from, to, step_max); + }, + clear: function() { return addon.remove_wot(this.instanceID); } diff --git a/native/Cargo.lock b/native/Cargo.lock index 095b10c..61a44fc 100644 --- a/native/Cargo.lock +++ b/native/Cargo.lock @@ -76,7 +76,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "duniter-wotb" -version = "0.7.1" +version = "0.8.0-a0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -352,7 +352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "wotb-rs" version = "0.1.0" dependencies = [ - "duniter-wotb 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "duniter-wotb 0.8.0-a0.5 (registry+https://github.com/rust-lang/crates.io-index)", "neon 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "neon-build 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -369,7 +369,7 @@ dependencies = [ "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum cslice 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "697c714f50560202b1f4e2e09cd50a421881c83e9025db75d15f276616f04f40" -"checksum duniter-wotb 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "834b85bd66552e19e45245c3fe2f96bd350fa11adad679902ae6a127ed9f4dc1" +"checksum duniter-wotb 0.8.0-a0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "873a948b6755405ec2da9f25b1266fcfaf45f9ef043b08e01eab4a6f91e9e6ad" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" diff --git a/native/Cargo.toml b/native/Cargo.toml index 715d044..6cf4c9e 100644 --- a/native/Cargo.toml +++ b/native/Cargo.toml @@ -15,4 +15,4 @@ neon-build = "0.1.22" [dependencies] neon = "0.1.22" num_cpus = "1.8.0" -duniter-wotb = "0.7.1" +duniter-wotb = "0.8.0-a0.5" diff --git a/native/src/lib.rs b/native/src/lib.rs index 846077e..52005fb 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -4,15 +4,19 @@ extern crate neon; extern crate duniter_wotb; extern crate num_cpus; -use duniter_wotb::rusty::RustyWebOfTrust; -use duniter_wotb::{HasLinkResult, NewLinkResult, NodeId, RemLinkResult, WebOfTrust, WotDistance, - WotDistanceParameters}; +use duniter_wotb::data::rusty::RustyWebOfTrust; +use duniter_wotb::data::{HasLinkResult, NewLinkResult, NodeId, RemLinkResult, WebOfTrust}; +use duniter_wotb::operations::distance::{DistanceCalculator, RustyDistanceCalculator, WotDistance, + WotDistanceParameters}; +use duniter_wotb::operations::path::{PathFinder, RustyPathFinder}; use neon::js::{JsArray, JsBoolean, JsInteger, JsNumber, JsObject, JsString, Object}; use neon::vm::{Call, JsResult}; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; static mut WOT_INSTANCES: Option<HashMap<usize, Box<RustyWebOfTrust>>> = None; +static DISTANCE_CALCULATOR: RustyDistanceCalculator = RustyDistanceCalculator {}; +static PATH_FINDER: RustyPathFinder = RustyPathFinder {}; fn get_wots() -> &'static mut HashMap<usize, Box<RustyWebOfTrust>> { unsafe { @@ -82,9 +86,13 @@ fn new_memory_instance(call: Call) -> JsResult<JsInteger> { fn mem_copy(call: Call) -> JsResult<JsInteger> { let scope = call.scope; - let instance_id = try!(try!(call.arguments.require(scope, 0)).check::<JsInteger>()).value() as usize; + let instance_id = + try!(try!(call.arguments.require(scope, 0)).check::<JsInteger>()).value() as usize; let wots = get_wots(); - let wot_copy = wots.get(&instance_id).expect("This instance don't exist !").deref().clone(); + let wot_copy = wots.get(&instance_id) + .expect("This instance don't exist !") + .deref() + .clone(); let mut new_instance_id = 0; while wots.contains_key(&new_instance_id) { new_instance_id += 1; @@ -123,18 +131,18 @@ fn is_enabled(call: Call) -> JsResult<JsBoolean> { } } -fn get_enabled(call: Call) -> JsResult<JsObject> { +fn get_enabled(call: Call) -> JsResult<JsArray> { let scope = call.scope; let instance_id = try!(try!(call.arguments.require(scope, 0)).check::<JsInteger>()).value(); let enabled = get_mut_wot(instance_id as usize).get_enabled(); - let mut js_array = JsObject::new(scope); + let mut js_array = JsArray::new(scope, enabled.len() as u32); let mut index: u32 = 0; for node_id in enabled { - let _bool = JsObject::set( + let _bool = try!(JsArray::set( *js_array.deref_mut(), index, JsInteger::new(scope, node_id.0 as i32), - ); + )); index += 1; } Ok(js_array) @@ -147,11 +155,50 @@ fn get_disabled(call: Call) -> JsResult<JsArray> { let js_array = JsArray::new(scope, disabled.len() as u32); let mut index: u32 = 0; for node_id in disabled { - let _bool = JsArray::set( + let _bool = try!(JsArray::set( + *js_array.deref(), + index, + JsInteger::new(scope, node_id.0 as i32), + )); + index += 1; + } + Ok(js_array) +} + +fn get_sentries(call: Call) -> JsResult<JsArray> { + let scope = call.scope; + let instance_id = try!(try!(call.arguments.require(scope, 0)).check::<JsInteger>()).value(); + let sentry_requirement = + try!(try!(call.arguments.require(scope, 1)).check::<JsInteger>()).value(); + let sentries = get_mut_wot(instance_id as usize).get_sentries(sentry_requirement as usize); + let js_array = JsArray::new(scope, sentries.len() as u32); + let mut index: u32 = 0; + for node_id in sentries { + let _bool = try!(JsArray::set( + *js_array.deref(), + index, + JsInteger::new(scope, node_id.0 as i32), + )); + index += 1; + } + Ok(js_array) +} + +fn get_non_sentries(call: Call) -> JsResult<JsArray> { + let scope = call.scope; + let instance_id = try!(try!(call.arguments.require(scope, 0)).check::<JsInteger>()).value(); + let sentry_requirement = + try!(try!(call.arguments.require(scope, 1)).check::<JsInteger>()).value(); + let non_sentries = + get_mut_wot(instance_id as usize).get_non_sentries(sentry_requirement as usize); + let js_array = JsArray::new(scope, non_sentries.len() as u32); + let mut index: u32 = 0; + for node_id in non_sentries { + let _bool = try!(JsArray::set( *js_array.deref(), index, JsInteger::new(scope, node_id.0 as i32), - ); + )); index += 1; } Ok(js_array) @@ -252,6 +299,7 @@ fn compute_distance(call: Call) -> JsResult<JsObject> { step_max, x_percent, }; + let wot = get_wot(instance_id as usize); let WotDistance { sentries, success, @@ -259,43 +307,71 @@ fn compute_distance(call: Call) -> JsResult<JsObject> { reached, reached_at_border, outdistanced, - } = get_wot(instance_id as usize) - .compute_distance(distance_params) + } = DISTANCE_CALCULATOR + .compute_distance(wot, distance_params) .unwrap(); let js_object = JsObject::new(scope); - let _bool = JsObject::set( + let _bool = try!(JsObject::set( *js_object.deref(), "sentries", JsInteger::new(scope, sentries as i32), - ); - let _bool = JsObject::set( + )); + let _bool = try!(JsObject::set( *js_object.deref(), "success", JsInteger::new(scope, success as i32), - ); - let _bool = JsObject::set( + )); + let _bool = try!(JsObject::set( *js_object.deref(), "success_at_border", JsInteger::new(scope, success_at_border as i32), - ); - let _bool = JsObject::set( + )); + let _bool = try!(JsObject::set( *js_object.deref(), "reached", JsInteger::new(scope, reached as i32), - ); - let _bool = JsObject::set( + )); + let _bool = try!(JsObject::set( *js_object.deref(), "reached_at_border", JsInteger::new(scope, reached_at_border as i32), - ); - let _bool = JsObject::set( + )); + let _bool = try!(JsObject::set( *js_object.deref(), "outdistanced", JsBoolean::new(scope, outdistanced), - ); + )); Ok(js_object) } +fn find_paths(call: Call) -> JsResult<JsArray> { + let scope = call.scope; + let instance_id = + try!(try!(call.arguments.require(scope, 0)).check::<JsInteger>()).value() as usize; + let from = try!(try!(call.arguments.require(scope, 1)).check::<JsInteger>()).value() as u32; + let to = try!(try!(call.arguments.require(scope, 2)).check::<JsInteger>()).value() as u32; + let step_max = try!(try!(call.arguments.require(scope, 3)).check::<JsInteger>()).value() as u32; + let wot = get_wot(instance_id as usize); + let paths = PATH_FINDER.find_paths(wot, NodeId(from as usize), NodeId(to as usize), step_max); + let mut i: u32 = 0; + let js_paths = JsArray::new(scope, paths.len() as u32); + for path in paths { + let mut j: u32 = 0; + let js_path = JsArray::new(scope, path.len() as u32); + for node_id in path { + let _bool = try!(JsArray::set( + *js_path.deref(), + j, + JsInteger::new(scope, node_id.0 as i32), + )); + j += 1; + } + let _bool = try!(JsArray::set(*js_paths.deref(), i, js_path,)); + i += 1; + } + Ok(js_paths) +} + fn remove_wot(call: Call) -> JsResult<JsBoolean> { let scope = call.scope; let instance_id = @@ -319,6 +395,8 @@ register_module!(m, { m.export("is_enabled", is_enabled)?; m.export("get_enabled", get_enabled)?; m.export("get_disabled", get_disabled)?; + m.export("get_sentries", get_sentries)?; + m.export("get_non_sentries", get_non_sentries)?; m.export("exist_link", exist_link)?; m.export("set_max_links", set_max_links)?; m.export("add_node", add_node)?; @@ -327,6 +405,7 @@ register_module!(m, { m.export("add_link", add_link)?; m.export("rem_link", rem_link)?; m.export("compute_distance", compute_distance)?; + m.export("find_paths", find_paths)?; m.export("remove_wot", remove_wot)?; Ok(()) }); diff --git a/package.json b/package.json index 4785100..292765f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "repository": { "type": "git", - "url": "https://git.duniter.org/nodes/typescript/wotb-rust" + "url": "https://git.duniter.org/nodes/typescript/wotb-rs" }, "author": "librelois <elois@ifee.fr>", "license": "AGPL-3.0", diff --git a/tests/test.js b/tests/test.js index 2ebc803..bcdf8fc 100644 --- a/tests/test.js +++ b/tests/test.js @@ -30,7 +30,7 @@ function testSuite(title, mode) { if (mode === FILE_MODE) { let wot = addon.newFileInstance(FILE); launchTests(wot, () => { - wot.drop(); + wot.clear(); wot.setMaxCert(3); }); } else { @@ -60,12 +60,16 @@ function testSuite(title, mode) { should.equal(wot.addNode(), 0); should.equal(wot.getWoTSize(), 1); should.equal(wot.isEnabled(0), true); - should.equal(wot.getEnabled().length, 1); + var enabled = wot.getEnabled(); + should.equal(enabled.length, 1); + should.equal(enabled[0], 0); should.equal(wot.getDisabled().length, 0); // Add another should.equal(wot.addNode(), 1); should.equal(wot.getWoTSize(), 2); - should.equal(wot.getEnabled().length, 2); + var enabled = wot.getEnabled(); + should.equal(enabled.length, 2); + should.equal(enabled[1], 1); should.equal(wot.getDisabled().length, 0); // Add 10 nodes for (let i = 0; i < 10; i++) { @@ -190,6 +194,13 @@ function testSuite(title, mode) { * 3 --> 2 */ should.equal(wot.getWoTSize(), 12); + should.equal(wot.getSentries(FROM_1_LINK_SENTRIES).length, 1); + should.equal(wot.getSentries(FROM_1_LINK_SENTRIES)[0], 2); + should.equal(wot.getSentries(FROM_2_LINKS_SENTRIES).length, 0); + should.equal(wot.getSentries(FROM_3_LINKS_SENTRIES).length, 0); + should.equal(wot.getNonSentries(FROM_1_LINK_SENTRIES).length, 11); // 12 - 1 = 11 + should.equal(wot.getNonSentries(FROM_2_LINKS_SENTRIES).length, 12); // 12 - 0 = 12 + should.equal(wot.getNonSentries(FROM_3_LINKS_SENTRIES).length, 12); // 12 - 0 = 12 should.equal(wot.isOutdistanced(0, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, X_PERCENT), __OK__); // OK: 2 --> 0 should.equal(wot.isOutdistanced(0, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_1, X_PERCENT), __OK__); // OK: 2 --> 0 should.equal(wot.isOutdistanced(0, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_1, X_PERCENT), __OK__); // OK: no sentry with 3 links issued @@ -199,6 +210,19 @@ function testSuite(title, mode) { wot.addLink(2, 3); should.equal(wot.getWoTSize(), 12); + should.equal(wot.getSentries(FROM_1_LINK_SENTRIES).length, 3); + should.equal(wot.getSentries(FROM_1_LINK_SENTRIES)[0], 1); + should.equal(wot.getSentries(FROM_1_LINK_SENTRIES)[1], 2); + should.equal(wot.getSentries(FROM_1_LINK_SENTRIES)[2], 3); + should.equal(wot.getSentries(FROM_2_LINKS_SENTRIES).length, 1); + should.equal(wot.getSentries(FROM_2_LINKS_SENTRIES)[0], 3); + should.equal(wot.getSentries(FROM_3_LINKS_SENTRIES).length, 0); + should.equal(wot.getNonSentries(FROM_1_LINK_SENTRIES).length, 9); // 12 - 3 = 9 + should.equal(wot.getNonSentries(FROM_2_LINKS_SENTRIES).length, 11); // 12 - 1 = 11 + should.equal(wot.getNonSentries(FROM_3_LINKS_SENTRIES).length, 12); // 12 - 0 = 12 + should.equal(wot.getPaths(3, 0, MAX_DISTANCE_1).length, 0); // KO + should.equal(wot.getPaths(3, 0, MAX_DISTANCE_2).length, 1); // It exists 3 --> 2 --> 0 + should.equal(wot.getPaths(3, 0, MAX_DISTANCE_2)[0].length, 3); // It exists 3 --> 2 --> 0 should.equal(wot.isOutdistanced(0, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, X_PERCENT), __OUTDISTANCED__); // KO: No path 3 --> 0 should.equal(wot.isOutdistanced(0, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_1, X_PERCENT), __OUTDISTANCED__); // KO: No path 3 --> 0 should.equal(wot.isOutdistanced(0, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_1, X_PERCENT), __OK__); // OK: no sentry with 3 links issued @@ -220,7 +244,9 @@ function testSuite(title, mode) { it('should work with member 3 disabled', function() { // With member 3 disabled (non-member) should.equal(wot.setEnabled(false, 3), false); - should.equal(wot.getDisabled().length, 1); + let disabled_nodes = wot.getDisabled(); + should.equal(disabled_nodes.length, 1); + should.equal(disabled_nodes[0], 3); should.equal(wot.isOutdistanced(0, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_1, X_PERCENT), __OK__); // OK: No path 3 --> 0, but is disabled }); @@ -241,5 +267,222 @@ function testSuite(title, mode) { after(cleanInstance); })); + + describe('Building a larger WoT', newInstance((wot, cleanInstance) => { + + before(() => { + cleanInstance(); + /** + * We build WoT: + * + * 0 --> 1 --> 2 --> 4 --> 5 <==> 6 --> 7 + * ^ + * || + * ##==> 3 <-- 8 <-- 9 <========## + * | || + * `> 10 <==> 11 <===## + */ + // Add nodes + for (let i = 0; i < 12; i++) { + should.equal(wot.addNode(), i); + } + // First line + should.equal(wot.addLink(0, 1), 1); + should.equal(wot.addLink(1, 2), 1); + should.equal(wot.addLink(2, 4), 1); + should.equal(wot.addLink(4, 5), 1); + should.equal(wot.addLink(5, 6), 1); + should.equal(wot.addLink(6, 7), 1); + should.equal(wot.addLink(6, 5), 2); + // 2n level + should.equal(wot.addLink(2, 3), 1); + should.equal(wot.addLink(3, 2), 2); + should.equal(wot.addLink(8, 3), 2); + should.equal(wot.addLink(9, 8), 1); + // 3rd level + should.equal(wot.addLink(8, 10), 1); + should.equal(wot.addLink(10, 11), 1); + should.equal(wot.addLink(11, 10), 2); + should.equal(wot.addLink(11, 9), 1); + should.equal(wot.addLink(9, 11), 2); + + should.equal(wot.getWoTSize(), 12); + return Promise.resolve(); + }); + + it('should have an initial size of 0', function() { + should.equal(wot.getWoTSize(), 12); + }); + + describe('testing around 2 with d = 1', () => { + + /** + * Sentries of 1 link (X are not sentries): + * + * X --> 1 --> 2 --> 4 --> 5 <==> 6 --> X + * ^ + * || + * ##==> 3 <-- 8 <-- 9 <========## + * | || + * `> 10 <==> 11 <===## + */ + // => It can be seen 1..6, 8..11 = 10 sentries + // => MINUS the sentry #2 (which is tested and is not to be included) + // => 9 sentries TESTED against member#2 + + it('should have 10 sentries', function() { + should.equal(wot.getSentries(FROM_1_LINK_SENTRIES).length, 10); + }); + + it('distance k = 1', function() { + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, _100_PERCENT), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, 0.5), __OUTDISTANCED__); + // 20% of the sentries: OK + // => 20% x 9 = 2 sentries to reach + // => we have 1 --> 2 + // => we have 3 --> 2 + // => OK (1,3) + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, 0.2), __OK__); + // Who can pass 20% can pass 10% + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, 0.1), __OK__); + // Can pass 23% (1,98 => 2 sentries) + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, 0.22), __OK__); + // But cannot pass 23% (2,07 => 3 sentries) + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_1, 0.23), __OUTDISTANCED__); + }); + + it('distance k = 2', function() { + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_2, _100_PERCENT), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_2, 0.5), __OUTDISTANCED__); + // 33% of the sentries: OK + // => 33% x 9 = 3 sentries to reach + // With k = 2 we have the following paths: + // 1 --> 2 + // 8 --> 3 --> 2 + // => OK (1,8,3) + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_2, 0.33), __OK__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_2, 0.3), __OK__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_2, 0.2), __OK__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_2, 0.1), __OK__); + // But cannot pass 34% (3,06 => 4 sentries) + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_2, 0.34), __OUTDISTANCED__); + }); + + it('distance k = 5', function() { + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_5, _100_PERCENT), __OUTDISTANCED__); + // 66% of the sentries: OK + // => 66% x 9 = 6 sentries to reach + // With k = 5 we have the following paths: + // 1 --> 2 + // 10 --> 11 --> 9 --> 8 --> 3 --> 2 + // => OK (1,10,11,9,8,3) + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_5, 0.66), __OK__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_5, 0.3), __OK__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_5, 0.2), __OK__); + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_5, 0.1), __OK__); + // But cannot pass 67% (6,03 => 7 sentries) + should.equal(wot.isOutdistanced(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_5, 0.67), __OUTDISTANCED__); + assert.deepEqual(wot.detailedDistance(2, FROM_1_LINK_SENTRIES, MAX_DISTANCE_5, 0.67), { + nbReached: 7, // +1 compared to reached sentries, because of member `0` + nbSuccess: 6, + nbSentries: 9, + isOutdistanced: true + }); + }); + }); + + describe('testing around 2 with d = 2', () => { + /** + * Sentries of 2 links (X are not sentries): + * + * X --> X --> 2 --> X --> X <==> X --> X + * ^ + * || + * ##==> X <-- X <-- X <========## + * | || + * `> X <==> 11 <===## + */ + // => It can be seen 2,6,8,9,11 = 5 sentries + // => MINUS the sentry #2 (which is tested and is not to be included) + // => 4 sentries + + it('should have 2 sentries', function() { + should.equal(wot.getSentries(FROM_2_LINKS_SENTRIES).length, 2); + }); + + it('distance k = 1', function() { + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_1, _100_PERCENT), __OUTDISTANCED__); + // With k = 1 we have no paths + // => ALWAYS KO + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_1, 0.99), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_1, 0.5), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_1, 0.01), __OUTDISTANCED__); + }); + + it('distance k = 2', function() { + // Always distanced with k = 2 + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_2, _100_PERCENT), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_2, 0.25), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_2, 0.24), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_2, 0.251), __OUTDISTANCED__); + }); + + it('distance k = 3', function() { + // Always distanced with k = 2 + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_3, _100_PERCENT), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_3, 0.50), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_3, 0.49), __OUTDISTANCED__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_3, 0.51), __OUTDISTANCED__); + }); + + it('distance k = 4', function() { + // Only 1 sentry at distance 4: always OK + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_4, _100_PERCENT), __OK__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_4, 0.75), __OK__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_4, 0.01), __OK__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_4, 0.99), __OK__); + }); + + it('distance k = 5', function() { + // Only 1 sentry at distance 4: always OK + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_5, _100_PERCENT), __OK__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_5, 0.75), __OK__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_5, 0.01), __OK__); + should.equal(wot.isOutdistanced(2, FROM_2_LINKS_SENTRIES, MAX_DISTANCE_5, 0.99), __OK__); + }); + }); + + describe('testing around 2 with d = 3', () => { + /** + * Sentries of 3 links (X are not sentries): + * + * X --> X --> 2 --> X --> X <==> X --> X + * ^ + * || + * ##==> X <-- X <-- X <========## + * | || + * `> X <==> X <===## + */ + // => It can be seen 2 = 1 sentries + // => MINUS the sentry #2 (which is tested and is not to be included) + // => 0 sentries + // => ALWAYS OK, no sentries to constraint + + it('distance k = 1', function() { + should.equal(wot.isOutdistanced(2, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_1, _100_PERCENT), __OK__); + should.equal(wot.isOutdistanced(2, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_1, 0.01), __OK__); + }); + + it('distance k = 2', function() { + should.equal(wot.isOutdistanced(2, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_2, _100_PERCENT), __OK__); + should.equal(wot.isOutdistanced(2, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_2, 0.01), __OK__); + }); + + it('distance k = 5', function() { + should.equal(wot.isOutdistanced(2, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_5, _100_PERCENT), __OK__); + should.equal(wot.isOutdistanced(2, FROM_3_LINKS_SENTRIES, MAX_DISTANCE_5, 0.01), __OK__); + }); + }); + })); }); } \ No newline at end of file -- GitLab