Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add list of services to enable (ECR-1766) & bundle btc-anchoring (ECR-1366) #338

Merged
merged 17 commits into from
Jul 7, 2018
7 changes: 7 additions & 0 deletions exonum-java-binding-core/rust/ejb-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ authors = ["Exonum team <[email protected]>"]
[dependencies]
java_bindings = { path = "..", features = ["invocation"] }
exonum-configuration = "0.8.0"
exonum-btc-anchoring = "0.8.1"
toml = "0.4.6"
serde = "1.0"
serde_derive = "1.0"

[dev-dependencies]
tempfile = "3"
15 changes: 10 additions & 5 deletions exonum-java-binding-core/rust/ejb-app/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
extern crate exonum_btc_anchoring;
extern crate exonum_configuration;
extern crate java_bindings;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use exonum_configuration::ServiceFactory as ConfigurationServiceFactory;
use java_bindings::exonum::helpers::fabric;
#[cfg(test)]
extern crate tempfile;

mod node_builder;

fn main() {
let builder = fabric::NodeBuilder::new()
.with_service(Box::new(java_bindings::JavaServiceFactory))
.with_service(Box::new(ConfigurationServiceFactory));
let builder = node_builder::create();
builder.run()
}
149 changes: 149 additions & 0 deletions exonum-java-binding-core/rust/ejb-app/src/node_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
use exonum_btc_anchoring::ServiceFactory as BtcAnchoringServiceFactory;
use exonum_configuration::ServiceFactory as ConfigurationServiceFactory;
use java_bindings::exonum::helpers::fabric::{self, ServiceFactory};
use java_bindings::JavaServiceFactory;
use toml;

use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Read;
use std::path::Path;

const PATH_TO_SERVICES_TO_ENABLE: &str = "ejb_app_services.toml";
const CONFIGURATION_SERVICE: &str = "configuration";
const BTC_ANCHORING_SERVICE: &str = "btc-anchoring";
const EJB_SERVICE: &str = "ejb-service";

#[derive(Serialize, Deserialize)]
struct ServicesToEnable {
services: HashSet<String>,
}

fn service_factories() -> HashMap<String, Box<ServiceFactory>> {
let mut service_factories = HashMap::new();
service_factories.insert(
CONFIGURATION_SERVICE.to_owned(),
Box::new(ConfigurationServiceFactory) as Box<ServiceFactory>,
);
service_factories.insert(
BTC_ANCHORING_SERVICE.to_owned(),
Box::new(BtcAnchoringServiceFactory) as Box<ServiceFactory>,
);
service_factories.insert(
EJB_SERVICE.to_owned(),
Box::new(JavaServiceFactory) as Box<ServiceFactory>,
);
service_factories
}

#[doc(hidden)]
pub fn services_to_enable<P: AsRef<Path>>(path: P) -> HashSet<String> {
// Return default list if config file not found.
let mut services = if let Ok(mut file) = File::open(path) {
let mut toml = String::new();
file.read_to_string(&mut toml).unwrap();
let ServicesToEnable { services } =
toml::from_str(&toml).expect("Invalid list of services to enable");
services
} else {
let mut services = HashSet::new();
services.insert(CONFIGURATION_SERVICE.to_owned());
services
};

// Add EJB_SERVICE if it's missing
services.insert(EJB_SERVICE.to_owned());

services
}

pub fn create() -> fabric::NodeBuilder {
let services = services_to_enable(PATH_TO_SERVICES_TO_ENABLE);
let mut service_factories = service_factories();

let mut builder = fabric::NodeBuilder::new();
for service_name in &services {
match service_factories.remove(service_name) {
Some(factory) => {
builder = builder.with_service(factory);
}
None => panic!("Found unknown service name {}", service_name),
}
}
builder
}

#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
use tempfile::{Builder, TempPath};

fn create_config(filename: &str, cfg: &str) -> TempPath {
let mut cfg_file = Builder::new().prefix(filename).tempfile().unwrap();
writeln!(cfg_file, "{}", cfg).unwrap();
cfg_file.into_temp_path()
}

#[test]
fn no_config() {
let services_to_enable = services_to_enable("");
assert_eq!(services_to_enable.len(), 2);
assert!(services_to_enable.contains(EJB_SERVICE));
assert!(services_to_enable.contains(CONFIGURATION_SERVICE));
}

#[test]
fn empty_list() {
let cfg = create_config("empty_list.toml", "services = []");
let services_to_enable = services_to_enable(cfg);
assert_eq!(services_to_enable.len(), 1);
assert!(services_to_enable.contains(EJB_SERVICE));
}

#[test]
fn duplicated() {
let cfg = create_config(
"duplicated.toml",
"services = [\"btc-anchoring\", \"btc-anchoring\"]",
);
let services_to_enable = services_to_enable(cfg);
assert_eq!(services_to_enable.len(), 2);
assert!(services_to_enable.contains(EJB_SERVICE));
assert!(services_to_enable.contains(BTC_ANCHORING_SERVICE));
}

#[test]
#[should_panic(expected = "Invalid list of services to enable")]
fn broken_config() {
let cfg = create_config("broken.toml", "not_list = 1");
let _services_to_enable = services_to_enable(cfg);
}

#[test]
fn with_anchoring() {
let cfg = create_config("anchoring.toml", "services = [\"btc-anchoring\"]");
let services_to_enable = services_to_enable(cfg);
assert_eq!(services_to_enable.len(), 2);
assert!(services_to_enable.contains(EJB_SERVICE));
assert!(services_to_enable.contains(BTC_ANCHORING_SERVICE));
}

#[test]
fn all_services() {
let cfg = create_config(
"all.toml",
"services = [\"configuration\", \"btc-anchoring\"]",
);
let services_to_enable = services_to_enable(cfg);
assert_eq!(services_to_enable.len(), 3);
assert!(services_to_enable.contains(EJB_SERVICE));
assert!(services_to_enable.contains(CONFIGURATION_SERVICE));
assert!(services_to_enable.contains(BTC_ANCHORING_SERVICE));

let service_factories = service_factories();
for service in &services_to_enable {
assert!(service_factories.get(service).is_some())
}
}
}
1 change: 1 addition & 0 deletions run_all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ mvn install \

# Run native integration tests that require a JVM.
./run_native_integration_tests.sh --skip-compile
./run_ejb_app_tests.sh --skip-compile
26 changes: 26 additions & 0 deletions run_ejb_app_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Runs EJB App tests (ejb-core/rust/ejb-app).
Copy link
Contributor

@dmitry-timofeev dmitry-timofeev Jul 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we call run_ejb_app_tests.sh from run_all_tests.sh run_native_integration_tests.sh?

Edit: I see, we do call from run_all_tests. Does it belong there or in native_its?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's just separated tests, not native_its

#
# ¡Keep it MacOS/Ubuntu compatible!

# Fail immediately in case of errors and/or unset variables
set -eu -o pipefail

# Use the Java that Maven uses.
#
# Unfortunately, a simple `which java` will not work for some users (e.g., jenv),
# hence this a bit complex thing.
JAVA_HOME="$(mvn --version | grep 'Java home' | sed 's/.*: //')"
echo "JAVA_HOME=${JAVA_HOME}"

# Find the directory containing libjvm (the relative path has changed in Java 9)
export LD_LIBRARY_PATH="$(find ${JAVA_HOME} -type f -name libjvm.* | xargs -n1 dirname)"
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"

cd exonum-java-binding-core/rust

# Stable works well unless you want benchmarks.
RUST_COMPILER_VERSION="stable"

cargo "+${RUST_COMPILER_VERSION}" test \
--manifest-path ejb-app/Cargo.toml