hashmap to vec in history, tests

This commit is contained in:
DieMyst 2021-01-06 23:44:04 +03:00
parent 13c957fc90
commit 32cbb81898
15 changed files with 1843 additions and 40 deletions

14
services/build.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
cd user-list-inmemory
cargo update
fce build --release
cd ../history-inmemory
cargo update
fce build --release
cd ../
rm -f artifacts/user-list.wasm
rm -f artifacts/history.wasm
cp user-list-inmemory/target/wasm32-wasi/release/user-list.wasm artifacts/
cp history-inmemory/target/wasm32-wasi/release/history.wasm artifacts/

View File

@ -2,9 +2,9 @@
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.34" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" checksum = "ee67c11feeac938fae061b232e38e0b6d94f97a9df10e6271319325ac4c56a86"
[[package]] [[package]]
name = "boolinator" name = "boolinator"
@ -70,11 +70,11 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.1.15" version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 1.0.0",
"libc", "libc",
"wasi", "wasi",
] ]
@ -102,15 +102,15 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "0.4.6" version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.80" version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -132,9 +132,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.4.1" version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
@ -178,9 +178,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.7" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -266,9 +266,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.59" version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -283,9 +283,9 @@ checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.48" version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -20,17 +20,16 @@ use crate::message::Message;
use crate::Result; use crate::Result;
use utils::*; use utils::*;
use once_cell::sync::{Lazy, OnceCell}; use once_cell::sync::{OnceCell};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::collections::HashMap;
static INSTANCE: OnceCell<Mutex<HashMap<u64, Message>>> = OnceCell::new(); static INSTANCE: OnceCell<Mutex<Vec<Message>>> = OnceCell::new();
pub fn init() -> Result<()> { pub fn init() -> Result<()> {
Ok(()) Ok(())
} }
fn get_data() -> &'static Mutex<HashMap<u64, Message>> { fn get_data() -> &'static Mutex<Vec<Message>> {
INSTANCE.get_or_init(|| { INSTANCE.get_or_init(|| {
<_>::default() <_>::default()
}) })
@ -41,7 +40,7 @@ pub fn add_message(msg: String) -> Result<u64> {
let id = usize_to_u64(data.len())?; let id = usize_to_u64(data.len())?;
data.insert(id, Message { id, body: msg }); data.push(Message { id, body: msg });
return Ok(id) return Ok(id)
@ -51,15 +50,13 @@ pub fn get_messages_with_limit(limit: u64) -> Result<Vec<Message>> {
let data = get_data().lock(); let data = get_data().lock();
let limit = u64_to_usize(limit)?; let limit = u64_to_usize(limit)?;
let mut msgs: Vec<Message> = data.values().map(|user| user.clone()).collect(); let msgs: Vec<Message> = data.to_vec().iter().rev().take(limit).map(|msg| msg.clone()).collect();
let last = &msgs[msgs.len() - limit..]; Ok(msgs)
Ok(last.to_vec())
} }
pub fn get_all_messages() -> Result<Vec<Message>> { pub fn get_all_messages() -> Result<Vec<Message>> {
let data = get_data().lock(); let data = get_data().lock();
Ok(data.values().map(|msg| msg.clone()).collect()) Ok(data.to_vec())
} }

View File

@ -16,14 +16,6 @@
use crate::Result; use crate::Result;
pub(super) fn u64_to_i64(value: u64) -> Result<i64> {
use crate::errors::HistoryError::InvalidArgument;
use std::convert::TryFrom;
i64::try_from(value)
.map_err(|_| InvalidArgument(format!("limit should be less than {}", i64::max_value())))
}
pub(super) fn u64_to_usize(value: u64) -> Result<usize> { pub(super) fn u64_to_usize(value: u64) -> Result<usize> {
use crate::errors::HistoryError::InvalidArgument; use crate::errors::HistoryError::InvalidArgument;
use std::convert::TryFrom; use std::convert::TryFrom;

1369
services/tests/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

15
services/tests/Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "services-test"
version = "0.1.0"
authors = ["Fluence Labs"]
edition = "2018"
[[bin]]
name = "services_test"
path = "src/main.rs"
[dev-dependencies]
fluence-app-service = "0.1.28"
uuid = { version = "0.8.1", features = ["v4"] }
serde = "1.0.117"
serde_json = "1.0.59"

View File

@ -0,0 +1,7 @@
modules_dir = "../artifacts"
[[module]]
name = "history"
mem_pages_count = 100
logger_enabled = true

View File

@ -0,0 +1,7 @@
modules_dir = "../artifacts"
[[module]]
name = "user-list"
mem_pages_count = 100
logger_enabled = true

View File

@ -0,0 +1,19 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// This project is intended only to test services that can't be compiled to the native target.
pub fn main() {}

View File

@ -0,0 +1,97 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
mod utils;
use utils::*;
use serde::Deserialize;
use serde::Serialize;
use serde_json::json;
const TEST_CONFIG_PATH: &str = "HistoryTestConfig.toml";
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct Message {
pub id: i64,
pub body: String,
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct GetMessagesServiceResult {
pub ret_code: i32,
pub err_msg: String,
pub messages: Vec<Message>,
}
#[test]
fn get_all() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let result = call_app_service!(app_service, "add", json!(["body_1"]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": "", "msg_id": 0 }));
let result = call_app_service!(app_service, "add", json!(["body_2"]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": "", "msg_id": 1 }));
let result = call_app_service!(app_service, "get_all", json!([]));
let result: GetMessagesServiceResult =
serde_json::from_value(result).expect("valid deserialization");
assert_eq!(result.ret_code, 0);
assert_eq!(
result.messages,
vec![
Message {
id: 0,
body: String::from("body_1"),
},
Message {
id: 1,
body: String::from("body_2"),
},
]
);
}
#[test]
fn get_last() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let messages_count = 10_000;
for i in 0..messages_count {
let body = format!("body_{}", i);
let result = call_app_service!(app_service, "add", json!([body]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "msg_id": i })
);
}
let result = call_app_service!(app_service, "get_last", json!([7]));
let result: GetMessagesServiceResult =
serde_json::from_value(result).expect("valid deserialization");
assert_eq!(result.messages.len(), 7);
assert_eq!(
result.messages[0],
Message {
id: messages_count - 1,
body: format!("body_{}", messages_count - 1),
}
);
}

View File

@ -0,0 +1,248 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
mod utils;
use utils::*;
use serde::Deserialize;
use serde::Serialize;
use serde_json::json;
const TEST_CONFIG_PATH: &str = "UserListTestConfig.toml";
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct User {
pub peer_id: String,
pub relay_id: String,
pub name: String,
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct GetUsersServiceResult {
pub ret_code: i32,
pub err_msg: String,
pub users: Vec<User>,
}
#[test]
fn add_delete_users() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let result = call_app_service!(
app_service,
"join",
json!([["peer_id", "relay_id", "name"]])
);
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
let result = call_app_service!(app_service, "get_users", json!([]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "users": [ {
"peer_id": "peer_id",
"relay_id": "relay_id",
"name": "name"
}]})
);
let result = call_app_service!(app_service, "delete", json!(["peer_id"]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": "" }));
let result = call_app_service!(app_service, "get_users", json!([]));
let get_users_result: GetUsersServiceResult =
serde_json::from_value(result).expect("success deserialization");
assert_eq!(get_users_result.ret_code, 0);
assert!(get_users_result.users.is_empty());
}
#[test]
fn add_delete_many_users() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let user_count = 10_000;
let mut users = Vec::with_capacity(user_count);
for i in 0..user_count {
let user = User {
peer_id: format!("peer_id_{}", i),
relay_id: format!("relay_id_{}", i),
name: format!("name_{}", i),
};
users.push(user.clone());
let user = serde_json::to_value(user).expect("success serialization");
let result = call_app_service!(app_service, "join", json!([user]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
}
let result = call_app_service!(app_service, "get_users", json!([]));
let get_users_result: GetUsersServiceResult =
serde_json::from_value(result).expect("success deserialization");
assert_eq!(get_users_result.ret_code, 0);
assert_eq!(get_users_result.users.len(), users.len());
for i in 0..user_count {
let user_id = format!("peer_id_{}", i);
let result = call_app_service!(app_service, "delete", json!([user_id]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": "" }));
}
let result = call_app_service!(app_service, "get_users", json!([]));
let get_users_result: GetUsersServiceResult =
serde_json::from_value(result).expect("success deserialization");
assert_eq!(get_users_result.ret_code, 0);
assert!(get_users_result.users.is_empty());
}
#[test]
fn is_exists() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let peer_id = String::from("peer_id");
let result = call_app_service!(app_service, "is_exists", json!([peer_id]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "is_exists": 0 })
);
let user = User {
peer_id: peer_id.clone(),
relay_id: String::from("relay_id"),
name: String::from("name"),
};
let user = serde_json::to_value(user).expect("success serialization");
let result = call_app_service!(app_service, "join", json!([user]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
let result = call_app_service!(app_service, "is_exists", json!([peer_id]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "is_exists": 1 })
);
let result = call_app_service!(app_service, "delete", json!(["peer_id"]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": "" }));
let result = call_app_service!(app_service, "is_exists", json!([peer_id]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "is_exists": 0 })
);
}
#[test]
fn unicode_symbols() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let peer_id = String::from("русский");
let user = User {
peer_id: peer_id.clone(),
relay_id: String::from("µµµµ"),
name: String::from("adasd"),
};
let user = serde_json::to_value(user).expect("valid serialization");
let result = call_app_service!(app_service, "join", json!([user]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
let result = call_app_service!(app_service, "is_exists", json!([peer_id]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "is_exists": 1 })
);
let result = call_app_service!(app_service, "get_users", json!([]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "users": [ user ]})
);
let result = call_app_service!(app_service, "delete", json!([peer_id]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": "" }));
let result = call_app_service!(app_service, "is_exists", json!([peer_id]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "is_exists": 0 })
);
}
#[test]
fn update_user_info() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let result = call_app_service!(
app_service,
"join",
json!([["peer_id", "relay_id", "name"]])
);
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
let result = call_app_service!(
app_service,
"join",
json!([[
"peer_id",
"relay_id_changed",
"name_changed"
]])
);
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
let result = call_app_service!(app_service, "get_users", json!([]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "users": [ {
"peer_id": "peer_id",
"relay_id": "relay_id_changed",
"name": "name_changed"
}]})
);
}
#[test]
fn get_user_by_peer_id() {
let mut app_service = create_app_service(TEST_CONFIG_PATH);
let result = call_app_service!(
app_service,
"join",
json!([["peer_id_1", "relay_id_1", "name_1"]])
);
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
let result = call_app_service!(
app_service,
"join",
json!([["peer_id_2", "relay_id_2", "name_2"]])
);
assert_eq!(result, json!({ "ret_code": 0, "err_msg": ""}));
let result = call_app_service!(app_service, "get_user", json!(["peer_id_1"]));
assert_eq!(
result,
json!({ "ret_code": 0, "err_msg": "", "users": [ {
"peer_id": "peer_id_1",
"relay_id": "relay_id_1",
"name": "name_1"
}]})
);
let result = call_app_service!(app_service, "get_user", json!(["peer_id_3"]));
assert_eq!(result, json!({ "ret_code": 0, "err_msg": "", "users": [] }));
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use fluence_app_service::AppService;
use fluence_app_service::TomlAppServiceConfig;
use std::collections::HashMap;
use std::path::PathBuf;
pub fn create_app_service<S: Into<PathBuf>>(config_file_path: S) -> AppService {
let tmp_path: String = std::env::temp_dir().to_string_lossy().into();
let service_id = uuid::Uuid::new_v4().to_string();
let mut config = TomlAppServiceConfig::load(config_file_path).expect("a valid config");
config.service_base_dir = Some(tmp_path);
AppService::new(config, &service_id, HashMap::new()).expect("app service is created")
}
#[macro_export]
macro_rules! call_app_service {
($app_service:expr, $func_name:expr, $arg:expr) => {
$app_service
.call($func_name, $arg, <_>::default())
.unwrap_or_else(|err| panic!("App service call failed: {}", err));
};
}

View File

@ -271,9 +271,9 @@ checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.57" version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6" checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -60,7 +60,7 @@ fn delete(peer_id: String) -> EmptyServiceResult {
is_authenticated()?; is_authenticated()?;
delete_user(peer_id) delete_user(peer_id)
}; }
delete_impl(peer_id).into() delete_impl(peer_id).into()
} }

View File

@ -23,5 +23,3 @@ pub struct User {
pub relay_id: String, pub relay_id: String,
pub name: String, pub name: String,
} }
pub(crate) const USER_FIELDS_COUNT: usize = 3;