Skip to content

Commit

Permalink
test: add test_schema_conflicts (#254)
Browse files Browse the repository at this point in the history
  • Loading branch information
dj8yfo committed Oct 25, 2023
1 parent 71a9d4d commit c8259fa
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 1 deletion.
7 changes: 6 additions & 1 deletion borsh/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,12 @@ pub fn add_definition(
match definitions.entry(declaration) {
Entry::Occupied(occ) => {
let existing_def = occ.get();
assert_eq!(existing_def, &definition, "Redefining type schema for the same type name. Types with the same names are not supported.");
assert_eq!(
existing_def,
&definition,
"Redefining type schema for {}. Types with the same names are not supported.",
occ.key()
);
}
Entry::Vacant(vac) => {
vac.insert(definition);
Expand Down
177 changes: 177 additions & 0 deletions borsh/tests/test_schema_conflict.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg(feature = "unstable__schema")]

#[cfg(feature = "std")]
use std::collections::{BTreeMap, BTreeSet};

#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::{
collections::{BTreeMap, BTreeSet},
format,
string::ToString,
vec::Vec,
};

use borsh::schema::{add_definition, Declaration, Definition, Fields};
use borsh::BorshSchema;

struct ConflictingSchema;

impl BorshSchema for ConflictingSchema {
#[inline]
fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
let fields = Fields::Empty;
let def = Definition::Struct { fields };
add_definition(Self::declaration(), def, definitions);
}
#[inline]
fn declaration() -> Declaration {
"i64".into()
}
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_conflict() {
let mut defs = Default::default();
<Vec<i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);

<ConflictingSchema as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_vec() {
let mut defs = Default::default();
<Vec<i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<Vec<ConflictingSchema> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_range() {
let mut defs = Default::default();
<core::ops::Range<i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<core::ops::Range<ConflictingSchema> as borsh::BorshSchema>::add_definitions_recursively(
&mut defs,
);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_slice() {
let mut defs = Default::default();
<[i64] as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<[ConflictingSchema] as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_array() {
let mut defs = Default::default();
<[i64; 10] as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<[ConflictingSchema; 10] as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_option() {
let mut defs = Default::default();
<Option<i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<Option<ConflictingSchema> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[allow(unused)]
#[derive(borsh::BorshSchema)]
struct GenericStruct<T> {
field: T,
}

#[test]
fn test_implicit_conflict_struct() {
let mut defs = Default::default();
<GenericStruct<i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<GenericStruct<ConflictingSchema> as borsh::BorshSchema>::add_definitions_recursively(
&mut defs,
);
// NOTE: the contents of `defs` depend on the order of 2 above lines
// this loophole is needed to enable derives for recursive structs/enums
}

#[allow(unused)]
#[derive(borsh::BorshSchema)]
struct SelfConflictingStruct {
field_1: i64,
field_2: ConflictingSchema,
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_self_conflicting_struct() {
let mut defs = Default::default();
<SelfConflictingStruct as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[allow(unused)]
#[derive(borsh::BorshSchema)]
enum GenericEnum<T> {
A { field: T },
B(u64),
}

#[test]
fn test_implicit_conflict_enum() {
let mut defs = Default::default();
<GenericEnum<i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<GenericEnum<ConflictingSchema> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
// NOTE: the contents of `defs` depend on the order of 2 above lines
// this loophole is needed to enable derives for recursive structs/enums
}

#[allow(unused)]
#[derive(borsh::BorshSchema)]
enum SelfConflictingEnum {
A { field: i64 },
B { field: ConflictingSchema },
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_self_conflicting_enum() {
let mut defs = Default::default();
<SelfConflictingEnum as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_result() {
let mut defs = Default::default();
<Result<u8, i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<Result<u8, ConflictingSchema> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_btreemap() {
let mut defs = Default::default();
<BTreeMap<i64, u8> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<BTreeMap<ConflictingSchema, u8> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_btreeset() {
let mut defs = Default::default();
<BTreeSet<i64> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<BTreeSet<ConflictingSchema> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

#[test]
#[should_panic(expected = "Redefining type schema for i64")]
fn test_implicit_conflict_tuple() {
let mut defs = Default::default();
<(i64, u8) as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
<(ConflictingSchema, u8) as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
}

0 comments on commit c8259fa

Please sign in to comment.