Skip to content

Commit

Permalink
Testkit to protobuf (#1078)
Browse files Browse the repository at this point in the history
  • Loading branch information
dvush authored and aleksuss committed Dec 5, 2018
1 parent e804b1b commit 5c82a19
Show file tree
Hide file tree
Showing 24 changed files with 451 additions and 74 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -80,6 +80,10 @@ The project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
of the result is now the equivalent of there being no description
of the result. (#1075)

#### exonum-testkit

- Structures in tests and examples are serialized using protobuf now. (#1078)

#### exonum-configuration

- The `Vote` and `VoteAgainst` now save the transaction hash instead of
Expand Down
5 changes: 2 additions & 3 deletions examples/cryptocurrency-advanced/backend/build.rs
@@ -1,10 +1,9 @@
extern crate exonum_build;

use exonum_build::protobuf_generate;
use std::env;
use exonum_build::{get_exonum_protobuf_files_path, protobuf_generate};

fn main() {
let exonum_protos = env::var("DEP_EXONUM_PROTOBUF_PROTOS").unwrap();
let exonum_protos = get_exonum_protobuf_files_path();
protobuf_generate(
"src/proto",
&["src/proto", &exonum_protos],
Expand Down
24 changes: 23 additions & 1 deletion exonum_build/src/lib.rs
Expand Up @@ -102,7 +102,7 @@ fn generate_mod_rs<P: AsRef<Path>, Q: AsRef<Path>>(
///
/// include!(concat!(env!("OUT_DIR"), "/example_mod.rs"));
///
/// // If you use types from exonum .proto files.
/// // If you use types from `exonum` .proto files.
/// use exonum::encoding::protobuf::*;
/// ```
pub fn protobuf_generate<P, R, I, T>(input_dir: P, includes: I, mod_file_name: T)
Expand Down Expand Up @@ -151,3 +151,25 @@ where
.expect("Input dir name is not convertible to &str")
);
}

/// Get path to the folder containing `exonum` protobuf files.
///
/// Needed for code generation of .proto files which import `exonum` provided .proto files.
///
/// # Examples
///
/// ```no_run
/// extern crate exonum_build;
///
/// use exonum_build::{protobuf_generate, get_exonum_protobuf_files_path};
///
/// let exonum_protos = get_exonum_protobuf_files_path();
/// protobuf_generate(
/// "src/proto",
/// &["src/proto", &exonum_protos],
/// "protobuf_mod.rs",
/// );
/// ```
pub fn get_exonum_protobuf_files_path() -> String {
env::var("DEP_EXONUM_PROTOBUF_PROTOS").expect("Failed to get exonum protobuf path")
}
5 changes: 5 additions & 0 deletions testkit/Cargo.toml
Expand Up @@ -38,3 +38,8 @@ pretty_assertions = "=0.5.1"
assert_matches = "1.2.0"
thread_local = "=0.3.6"
lazy_static = "1.0.0"
protobuf = { version = "=2.2.0", features = ["with-serde"] }
exonum_derive = { version = "0.9.0", path = "../exonum_derive" }

[build-dependencies]
exonum_build = { version = "0.9.0", path = "../exonum_build" }
34 changes: 34 additions & 0 deletions testkit/build.rs
@@ -0,0 +1,34 @@
extern crate exonum_build;

use exonum_build::{get_exonum_protobuf_files_path, protobuf_generate};

fn main() {
let exonum_protos = get_exonum_protobuf_files_path();
let protobuf_gen_data = [
("src/proto", vec!["src/proto"], "testkit_protobuf_mod.rs"),
(
"tests/inflating_currency/proto",
vec!["tests/inflating_currency/proto", &exonum_protos],
"currency_example_protobuf_mod.rs",
),
(
"tests/counter/proto",
vec!["tests/counter/proto"],
"counter_example_protobuf_mod.rs",
),
(
"tests/service_hooks/proto",
vec!["tests/service_hooks/proto"],
"hooks_example_protobuf_mod.rs",
),
(
"examples/timestamping/proto",
vec!["examples/timestamping/proto"],
"timestamping_example_protobuf_mod.rs",
),
];

for (input_dir, includes, mod_file_name) in protobuf_gen_data.into_iter() {
protobuf_generate(input_dir, includes, mod_file_name);
}
}
Expand Up @@ -12,13 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate exonum;
#[macro_use]
extern crate exonum_testkit;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum_derive;
extern crate protobuf;

use exonum::{
api::node::public::explorer::{BlocksQuery, BlocksRange, TransactionQuery},
Expand All @@ -32,21 +34,33 @@ use exonum::{
};
use exonum_testkit::{ApiKind, TestKitBuilder};

mod proto;

// Simple service implementation.

const SERVICE_ID: u16 = 512;

transactions! {
TimestampingServiceTransactions {
struct TxTimestamp {
msg: &str,
}
}
#[derive(Serialize, Deserialize, Clone, Debug, ProtobufConvert)]
#[exonum(pb = "proto::TxTimestamp")]
struct TxTimestamp {
message: String,
}

#[derive(Serialize, Deserialize, Clone, Debug, TransactionSet)]
enum TimestampingServiceTransactions {
TxTimestamp(TxTimestamp),
}

impl TxTimestamp {
fn sign(author: &PublicKey, msg: &str, key: &SecretKey) -> Signed<RawTransaction> {
Message::sign_transaction(TxTimestamp::new(msg), SERVICE_ID, *author, key)
fn sign(author: &PublicKey, message: &str, key: &SecretKey) -> Signed<RawTransaction> {
Message::sign_transaction(
Self {
message: message.to_owned(),
},
SERVICE_ID,
*author,
key,
)
}
}

Expand Down
26 changes: 26 additions & 0 deletions testkit/examples/timestamping/proto/mod.rs
@@ -0,0 +1,26 @@
// Copyright 2018 The Exonum Team
//
// 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.

//! Module of the rust-protobuf generated files.

// For protobuf generated files.
#![allow(bare_trait_objects)]
#![allow(renamed_and_removed_lints)]

pub use self::timestamping::TxTimestamp;

include!(concat!(
env!("OUT_DIR"),
"/timestamping_example_protobuf_mod.rs"
));
19 changes: 19 additions & 0 deletions testkit/examples/timestamping/proto/timestamping.proto
@@ -0,0 +1,19 @@
// Copyright 2018 The Exonum Team
//
// 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.

syntax = "proto3";

package exonum.testkit;

message TxTimestamp { string message = 1; }
8 changes: 7 additions & 1 deletion testkit/src/lib.rs
Expand Up @@ -143,7 +143,6 @@ extern crate actix_web;
#[cfg_attr(test, macro_use)]
#[cfg(test)]
extern crate assert_matches;
#[cfg_attr(test, macro_use)]
extern crate exonum;
#[macro_use]
extern crate failure;
Expand All @@ -154,6 +153,11 @@ extern crate reqwest;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[cfg_attr(test, macro_use)]
#[cfg(test)]
extern crate exonum_derive;
#[cfg(test)]
extern crate protobuf;
extern crate serde_json;
extern crate serde_urlencoded;
extern crate tokio_core;
Expand All @@ -163,6 +167,8 @@ pub use compare::ComparableSnapshot;
pub use network::{TestNetwork, TestNetworkConfiguration, TestNode};

pub mod compare;
#[cfg(test)]
pub mod proto;

use futures::{sync::mpsc, Future, Stream};
use tokio_core::reactor::Core;
Expand Down
20 changes: 20 additions & 0 deletions testkit/src/proto/mod.rs
@@ -0,0 +1,20 @@
// Copyright 2018 The Exonum Team
//
// 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.

//! Module of the rust-protobuf generated files.

#![allow(bare_trait_objects)]
#![allow(renamed_and_removed_lints)]

include!(concat!(env!("OUT_DIR"), "/testkit_protobuf_mod.rs"));
19 changes: 19 additions & 0 deletions testkit/src/proto/tests.proto
@@ -0,0 +1,19 @@
// Copyright 2018 The Exonum Team
//
// 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.

syntax = "proto3";

package exonum.testkit;

message TxTimestamp { string message = 1; }
26 changes: 18 additions & 8 deletions testkit/src/server.rs
Expand Up @@ -161,24 +161,34 @@ mod tests {
use exonum::messages::{Message, RawTransaction, Signed};
use exonum::storage::Snapshot;

use super::*;
use super::{super::proto, *};
use {TestKitApi, TestKitBuilder};

type DeBlock = BlockWithTransactions;
const TIMESTAMP_SERVICE_ID: u16 = 0;
transactions! {
Any {

struct TxTimestamp {
msg: &str,
}
}
#[derive(Serialize, Deserialize, Clone, Debug, ProtobufConvert)]
#[exonum(pb = "proto::tests::TxTimestamp")]
struct TxTimestamp {
message: String,
}

#[derive(Serialize, Deserialize, Clone, Debug, TransactionSet)]
enum Any {
TxTimestamp(TxTimestamp),
}

impl TxTimestamp {
fn for_str(s: &str) -> Signed<RawTransaction> {
let (pubkey, key) = gen_keypair();
Message::sign_transaction(TxTimestamp::new(s), TIMESTAMP_SERVICE_ID, pubkey, &key)
Message::sign_transaction(
Self {
message: s.to_owned(),
},
TIMESTAMP_SERVICE_ID,
pubkey,
&key,
)
}
}

Expand Down
34 changes: 22 additions & 12 deletions testkit/tests/counter/counter.rs
Expand Up @@ -24,6 +24,8 @@ use exonum::{
storage::{Entry, Fork, Snapshot},
};

use super::proto;

pub const SERVICE_ID: u16 = 1;

// "correct horse battery staple" brainwallet pubkey in Ed25519 with SHA-256 digest
Expand Down Expand Up @@ -71,44 +73,52 @@ impl<'a> CounterSchema<&'a mut Fork> {

// // // // Transactions // // // //

transactions! {
pub CounterTransactions {
#[derive(Serialize, Deserialize, Clone, Debug, ProtobufConvert)]
#[exonum(pb = "proto::TxReset")]
pub struct TxReset {}

struct TxIncrement {
by: u64,
}
#[derive(Serialize, Deserialize, Clone, Debug, ProtobufConvert)]
#[exonum(pb = "proto::TxIncrement")]
pub struct TxIncrement {
by: u64,
}

struct TxReset {
}
}
#[derive(Serialize, Deserialize, Clone, Debug, TransactionSet)]
pub enum CounterTransactions {
Increment(TxIncrement),
Reset(TxReset),
}

impl TxIncrement {
pub fn new(by: u64) -> Self {
Self { by }
}

pub fn sign(author: &PublicKey, by: u64, key: &SecretKey) -> Signed<RawTransaction> {
Message::sign_transaction(TxIncrement::new(by), SERVICE_ID, *author, key)
Message::sign_transaction(Self::new(by), SERVICE_ID, *author, key)
}
}

impl Transaction for TxIncrement {
// This method purposely does not check counter overflow in order to test
// behavior of panicking transactions.
fn execute(&self, mut tc: TransactionContext) -> ExecutionResult {
if self.by() == 0 {
if self.by == 0 {
Err(ExecutionError::with_description(
0,
"Adding zero does nothing!".to_string(),
))?;
}

let mut schema = CounterSchema::new(tc.fork());
schema.inc_count(self.by());
schema.inc_count(self.by);
Ok(())
}
}

impl TxReset {
pub fn sign(author: &PublicKey, key: &SecretKey) -> Signed<RawTransaction> {
Message::sign_transaction(TxReset::new(), SERVICE_ID, *author, key)
Message::sign_transaction(Self {}, SERVICE_ID, *author, key)
}
}

Expand Down

0 comments on commit 5c82a19

Please sign in to comment.