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
use holochain_core_types::cas::content::Address;
use holochain_wasm_utils::api_serialization::get_links::{GetLinksArgs, GetLinksResult};
use nucleus::ribosome::Runtime;
use serde_json;
use std::collections::HashSet;
use wasmi::{RuntimeArgs, RuntimeValue, Trap};
pub fn invoke_get_links(
runtime: &mut Runtime,
args: &RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
let args_str = runtime.load_utf8_from_args(&args);
let input: GetLinksArgs = match serde_json::from_str(&args_str) {
Ok(input) => input,
Err(_) => return ribosome_error_code!(ArgumentDeserializationFailed),
};
let get_links_result = runtime
.context
.state()
.unwrap()
.dht()
.get_links(input.entry_address, input.tag);
let json = serde_json::to_string(&GetLinksResult {
ok: get_links_result.is_ok(),
links: get_links_result
.clone()
.unwrap_or(HashSet::new())
.iter()
.map(|eav| eav.value())
.collect::<Vec<Address>>(),
error: get_links_result
.map_err(|holochain_error| holochain_error.to_string())
.err()
.unwrap_or(String::from("")),
}).expect("Could not serialize GetLinksResult");
runtime.store_utf8(&json)
}
#[cfg(test)]
pub mod tests {
extern crate test_utils;
extern crate wabt;
use agent::actions::commit::commit_entry;
use dht::actions::add_link::add_link;
use futures::executor::block_on;
use holochain_core_types::{
cas::content::Address, entry::Entry, entry_type::test_entry_type, links_entry::Link,
};
use holochain_wasm_utils::api_serialization::get_links::GetLinksArgs;
use instance::tests::{test_context_and_logger, test_instance};
use nucleus::ribosome::{
api::{tests::*, ZomeApiFunction},
Defn,
};
use serde_json;
pub fn test_get_links_args_bytes(base: &Address, tag: &str) -> Vec<u8> {
let args = GetLinksArgs {
entry_address: base.clone(),
tag: String::from(tag),
};
serde_json::to_string(&args)
.expect("args should serialize")
.into_bytes()
}
#[test]
fn returns_list_of_links() {
let wasm = test_zome_api_function_wasm(ZomeApiFunction::GetLinks.as_str());
let dna = test_utils::create_test_dna_with_wasm(
&test_zome_name(),
&test_capability(),
wasm.clone(),
);
let dna_name = &dna.name.to_string().clone();
let instance = test_instance(dna).expect("Could not create test instance");
let (context, _) = test_context_and_logger("joan");
let initialized_context = instance.initialize_context(context);
let mut entry_hashes: Vec<Address> = Vec::new();
for i in 0..3 {
let entry = Entry::new(&test_entry_type(), &format!("entry{} value", i));
let hash = block_on(commit_entry(
entry,
&initialized_context.action_channel.clone(),
&initialized_context,
)).expect("Could not commit entry for testing");
entry_hashes.push(hash);
}
let link1 = Link::new(&entry_hashes[0], &entry_hashes[1], "test-tag");
let link2 = Link::new(&entry_hashes[0], &entry_hashes[2], "test-tag");
assert!(block_on(add_link(&link1, &initialized_context)).is_ok());
assert!(block_on(add_link(&link2, &initialized_context)).is_ok());
let call_result = test_zome_api_function_call(
&dna_name,
initialized_context.clone(),
&instance,
&wasm,
test_get_links_args_bytes(&entry_hashes[0], "test-tag"),
);
let ordering1: bool = call_result
== format!(
r#"{{"ok":true,"links":["{}","{}"],"error":""}}"#,
entry_hashes[1], entry_hashes[2]
) + "\u{0}";
let ordering2: bool = call_result
== format!(
r#"{{"ok":true,"links":["{}","{}"],"error":""}}"#,
entry_hashes[2], entry_hashes[1]
) + "\u{0}";
assert!(ordering1 || ordering2);
let call_result = test_zome_api_function_call(
&dna_name,
initialized_context.clone(),
&instance,
&wasm,
test_get_links_args_bytes(&entry_hashes[0], "other-tag"),
);
assert_eq!(
call_result,
r#"{"ok":true,"links":[],"error":""}"#.to_string() + "\u{0}",
);
}
}