Skip to content

Commit 868b465

Browse files
authored
Add more tests for events.rs/decode_and_consume_type (paritytech#430)
* test-runtime: Fix README typo Signed-off-by: Alexandru Vasile <[email protected]> * test-runtime: Explicit error handling for missing substrate binary Signed-off-by: Alexandru Vasile <[email protected]> * test-runtime: Fix documentation typo Signed-off-by: Alexandru Vasile <[email protected]> * events: Test primitive decode_and_consume Signed-off-by: Alexandru Vasile <[email protected]> * events: Test tuple decode_and_consume Signed-off-by: Alexandru Vasile <[email protected]> * events: Test array decode_and_consume Signed-off-by: Alexandru Vasile <[email protected]> * events: Extend array with sequences Signed-off-by: Alexandru Vasile <[email protected]> * events: Test variant decode_and_consume Signed-off-by: Alexandru Vasile <[email protected]> * events: Test composite decode_and_consume Signed-off-by: Alexandru Vasile <[email protected]> * events: Test compact decode_and_consume Signed-off-by: Alexandru Vasile <[email protected]>
1 parent abd7a41 commit 868b465

File tree

3 files changed

+195
-3
lines changed

3 files changed

+195
-3
lines changed

subxt/src/events.rs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,17 @@ pub enum EventsDecodingError {
373373
mod tests {
374374
use super::*;
375375
use crate::{
376+
error::GenericError::{
377+
Codec,
378+
EventsDecoding,
379+
Other,
380+
},
381+
events::EventsDecodingError::UnsupportedPrimitive,
376382
Config,
377383
DefaultConfig,
378384
Phase,
379385
};
386+
use assert_matches::assert_matches;
380387
use codec::Encode;
381388
use frame_metadata::{
382389
v14::{
@@ -643,4 +650,185 @@ mod tests {
643650
bitvec::bitvec![Msb0, u64; 0, 1, 1, 0, 1, 0, 1, 0, 0],
644651
);
645652
}
653+
654+
#[test]
655+
fn decode_primitive() {
656+
decode_and_consume_type_consumes_all_bytes(false);
657+
decode_and_consume_type_consumes_all_bytes(true);
658+
659+
let dummy_data = vec![0u8];
660+
let dummy_cursor = &mut &*dummy_data;
661+
let (id, reg) = singleton_type_registry::<char>();
662+
let res = decode_and_consume_type(id.id(), &reg, dummy_cursor);
663+
assert_matches!(
664+
res,
665+
Err(EventsDecoding(UnsupportedPrimitive(TypeDefPrimitive::Char)))
666+
);
667+
668+
decode_and_consume_type_consumes_all_bytes("str".to_string());
669+
670+
decode_and_consume_type_consumes_all_bytes(1u8);
671+
decode_and_consume_type_consumes_all_bytes(1i8);
672+
673+
decode_and_consume_type_consumes_all_bytes(1u16);
674+
decode_and_consume_type_consumes_all_bytes(1i16);
675+
676+
decode_and_consume_type_consumes_all_bytes(1u32);
677+
decode_and_consume_type_consumes_all_bytes(1i32);
678+
679+
decode_and_consume_type_consumes_all_bytes(1u64);
680+
decode_and_consume_type_consumes_all_bytes(1i64);
681+
682+
decode_and_consume_type_consumes_all_bytes(1u128);
683+
decode_and_consume_type_consumes_all_bytes(1i128);
684+
}
685+
686+
#[test]
687+
fn decode_tuple() {
688+
decode_and_consume_type_consumes_all_bytes(());
689+
690+
decode_and_consume_type_consumes_all_bytes((true,));
691+
692+
decode_and_consume_type_consumes_all_bytes((true, "str"));
693+
694+
// Incomplete bytes for decoding
695+
let dummy_data = false.encode();
696+
let dummy_cursor = &mut &*dummy_data;
697+
let (id, reg) = singleton_type_registry::<(bool, &'static str)>();
698+
let res = decode_and_consume_type(id.id(), &reg, dummy_cursor);
699+
assert_matches!(res, Err(Codec(_)));
700+
701+
// Incomplete bytes for decoding, with invalid char type
702+
let dummy_data = (false, "str", 0u8).encode();
703+
let dummy_cursor = &mut &*dummy_data;
704+
let (id, reg) = singleton_type_registry::<(bool, &'static str, char)>();
705+
let res = decode_and_consume_type(id.id(), &reg, dummy_cursor);
706+
assert_matches!(
707+
res,
708+
Err(EventsDecoding(UnsupportedPrimitive(TypeDefPrimitive::Char)))
709+
);
710+
// The last byte (0x0 u8) should not be consumed
711+
assert_eq!(dummy_cursor.len(), 1);
712+
}
713+
714+
#[test]
715+
fn decode_array_and_seq() {
716+
decode_and_consume_type_consumes_all_bytes([0]);
717+
decode_and_consume_type_consumes_all_bytes([1, 2, 3, 4, 5]);
718+
decode_and_consume_type_consumes_all_bytes([0; 500]);
719+
decode_and_consume_type_consumes_all_bytes(["str", "abc", "cde"]);
720+
721+
decode_and_consume_type_consumes_all_bytes(vec![0]);
722+
decode_and_consume_type_consumes_all_bytes(vec![1, 2, 3, 4, 5]);
723+
decode_and_consume_type_consumes_all_bytes(vec!["str", "abc", "cde"]);
724+
}
725+
726+
#[test]
727+
fn decode_variant() {
728+
#[derive(Clone, Encode, TypeInfo)]
729+
enum EnumVar {
730+
A,
731+
B((&'static str, u8)),
732+
C { named: i16 },
733+
}
734+
const INVALID_TYPE_ID: u32 = 1024;
735+
736+
decode_and_consume_type_consumes_all_bytes(EnumVar::A);
737+
decode_and_consume_type_consumes_all_bytes(EnumVar::B(("str", 1)));
738+
decode_and_consume_type_consumes_all_bytes(EnumVar::C { named: 1 });
739+
740+
// Invalid variant index
741+
let dummy_data = 3u8.encode();
742+
let dummy_cursor = &mut &*dummy_data;
743+
let (id, reg) = singleton_type_registry::<EnumVar>();
744+
let res = decode_and_consume_type(id.id(), &reg, dummy_cursor);
745+
assert_matches!(res, Err(Other(_)));
746+
747+
// Valid index, incomplete data
748+
let dummy_data = 2u8.encode();
749+
let dummy_cursor = &mut &*dummy_data;
750+
let res = decode_and_consume_type(id.id(), &reg, dummy_cursor);
751+
assert_matches!(res, Err(Codec(_)));
752+
753+
let res = decode_and_consume_type(INVALID_TYPE_ID, &reg, dummy_cursor);
754+
assert_matches!(res, Err(crate::error::GenericError::Metadata(_)));
755+
}
756+
757+
#[test]
758+
fn decode_composite() {
759+
#[derive(Clone, Encode, TypeInfo)]
760+
struct Composite {}
761+
decode_and_consume_type_consumes_all_bytes(Composite {});
762+
763+
#[derive(Clone, Encode, TypeInfo)]
764+
struct CompositeV2 {
765+
id: u32,
766+
name: String,
767+
}
768+
decode_and_consume_type_consumes_all_bytes(CompositeV2 {
769+
id: 10,
770+
name: "str".to_string(),
771+
});
772+
773+
#[derive(Clone, Encode, TypeInfo)]
774+
struct CompositeV3<T> {
775+
id: u32,
776+
extra: T,
777+
}
778+
decode_and_consume_type_consumes_all_bytes(CompositeV3 {
779+
id: 10,
780+
extra: vec![0, 1, 2],
781+
});
782+
decode_and_consume_type_consumes_all_bytes(CompositeV3 {
783+
id: 10,
784+
extra: bitvec::bitvec![Lsb0, u8; 0, 1, 1, 0, 1],
785+
});
786+
decode_and_consume_type_consumes_all_bytes(CompositeV3 {
787+
id: 10,
788+
extra: ("str", 1),
789+
});
790+
decode_and_consume_type_consumes_all_bytes(CompositeV3 {
791+
id: 10,
792+
extra: CompositeV2 {
793+
id: 2,
794+
name: "str".to_string(),
795+
},
796+
});
797+
798+
#[derive(Clone, Encode, TypeInfo)]
799+
struct CompositeV4(u32, bool);
800+
decode_and_consume_type_consumes_all_bytes(CompositeV4(1, true));
801+
802+
#[derive(Clone, Encode, TypeInfo)]
803+
struct CompositeV5(u32);
804+
decode_and_consume_type_consumes_all_bytes(CompositeV5(1));
805+
}
806+
807+
#[test]
808+
fn decode_compact() {
809+
#[derive(Clone, Encode, TypeInfo)]
810+
enum Compact {
811+
A(#[codec(compact)] u32),
812+
}
813+
decode_and_consume_type_consumes_all_bytes(Compact::A(1));
814+
815+
#[derive(Clone, Encode, TypeInfo)]
816+
struct CompactV2(#[codec(compact)] u32);
817+
decode_and_consume_type_consumes_all_bytes(CompactV2(1));
818+
819+
#[derive(Clone, Encode, TypeInfo)]
820+
struct CompactV3 {
821+
#[codec(compact)]
822+
val: u32,
823+
}
824+
decode_and_consume_type_consumes_all_bytes(CompactV3 { val: 1 });
825+
826+
#[derive(Clone, Encode, TypeInfo)]
827+
struct CompactV4<T> {
828+
#[codec(compact)]
829+
val: T,
830+
}
831+
decode_and_consume_type_consumes_all_bytes(CompactV4 { val: 0u8 });
832+
decode_and_consume_type_consumes_all_bytes(CompactV4 { val: 1u16 });
833+
}
646834
}

test-runtime/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
The logic for this crate exists mainly in the `build.rs` file.
44

55
At compile time, this crate will:
6-
- Spin up a local `substrate` binary (set the `SUBSTRATE_NODE_PATH` env var to point to a custom binary, otehrwise it'll look for `substrate` on your PATH).
6+
- Spin up a local `substrate` binary (set the `SUBSTRATE_NODE_PATH` env var to point to a custom binary, otherwise it'll look for `substrate` on your PATH).
77
- Obtain metadata from this node.
88
- Export the metadata and a `node_runtime` module which has been annotated using the `subxt` proc macro and is based off the above metadata.
99

10-
The reason for doing this is that our integration tests (which also spin up a Substrate node) can then use the generated `subxt` types from the exact node being tested against, so that we don't have to worry about metadata getting out of sync with the binary under test.
10+
The reason for doing this is that our integration tests (which also spin up a Substrate node) can then use the generated `subxt` types from the exact node being tested against, so that we don't have to worry about metadata getting out of sync with the binary under test.

test-runtime/build.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ async fn run() {
5858
.spawn();
5959
let mut cmd = match cmd {
6060
Ok(cmd) => KillOnDrop(cmd),
61+
Err(ref e) if e.kind() == std::io::ErrorKind::NotFound => {
62+
panic!("A substrate binary should be installed on your path for testing purposes. \
63+
See https://github.com/paritytech/subxt/tree/master#integration-testing")
64+
}
6165
Err(e) => {
6266
panic!("Cannot spawn substrate command '{}': {}", substrate_bin, e)
6367
}
@@ -164,7 +168,7 @@ fn next_open_port() -> Option<u16> {
164168
}
165169
}
166170

167-
/// If the substrate process isn't explicilty killed on drop,
171+
/// If the substrate process isn't explicitly killed on drop,
168172
/// it seems that panics that occur while the command is running
169173
/// will leave it running and block the build step from ever finishing.
170174
/// Wrapping it in this prevents this from happening.

0 commit comments

Comments
 (0)