Skip to content

Commit

Permalink
feat(cognitarium): manage insert error cases
Browse files Browse the repository at this point in the history
  • Loading branch information
amimart committed Jun 1, 2023
1 parent f5d9c3d commit c10cf6a
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 27 deletions.
63 changes: 46 additions & 17 deletions contracts/okp4-cognitarium/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> StdResult<Binary> {
mod tests {
use super::*;
use crate::error::StoreError;
use crate::msg::ExecuteMsg::InsertData;
use crate::msg::{DataInput, StoreLimitsInput, StoreLimitsInputBuilder};
use crate::state;
use crate::state::{namespaces, triples, Namespace};
Expand Down Expand Up @@ -125,7 +126,8 @@ mod tests {
assert_eq!(
store.stat,
state::StoreStat {
triples_count: Uint128::zero(),
triple_count: Uint128::zero(),
byte_size: Uint128::zero(),
}
);

Expand All @@ -135,9 +137,22 @@ mod tests {
#[test]
fn proper_insert() {
let cases = vec![
DataInput::RDFXml(read_test_data("sample.rdf.xml")),
DataInput::Turtle(read_test_data("sample.ttl")),
DataInput::NTriples(read_test_data("sample.nt")),
InsertData {
format: Some(DataFormat::RDFXml),
data: read_test_data("sample.rdf.xml"),
},
InsertData {
format: Some(DataFormat::Turtle),
data: read_test_data("sample.ttl"),
},
InsertData {
format: Some(DataFormat::NTriples),
data: read_test_data("sample.nt"),
},
InsertData {
format: None,
data: read_test_data("sample.ttl"),
},
];

for case in cases {
Expand All @@ -154,12 +169,7 @@ mod tests {
)
.unwrap();

let res = execute(
deps.as_mut(),
mock_env(),
info.clone(),
ExecuteMsg::InsertData { input: case },
);
let res = execute(deps.as_mut(), mock_env(), info.clone(), case);

assert!(res.is_ok());
assert_eq!(
Expand All @@ -177,7 +187,7 @@ mod tests {
40
);
assert_eq!(
STORE.load(&deps.storage).unwrap().stat.triples_count,
STORE.load(&deps.storage).unwrap().stat.triple_count,
Uint128::from(40u128),
);
assert_eq!(NAMESPACE_KEY_INCREMENT.load(&deps.storage).unwrap(), 17u128);
Expand Down Expand Up @@ -213,8 +223,9 @@ mod tests {
deps.as_mut(),
mock_env(),
mock_info("not-owner", &[]),
ExecuteMsg::InsertData {
input: DataInput::RDFXml(Binary::from(&[])),
InsertData {
format: Some(DataFormat::RDFXml),
data: read_test_data("sample.rdf.xml"),
},
);
assert!(res.is_err());
Expand Down Expand Up @@ -256,11 +267,11 @@ mod tests {
),
(
StoreLimitsInputBuilder::default()
.max_insert_data_byte_size(50u128)
.max_insert_data_byte_size(500u128)
.build()
.unwrap(),
Some(ContractError::from(StoreError::MaxInsertDataByteSize(
50u128.into(),
500u128.into(),
))),
),
(
Expand All @@ -270,6 +281,23 @@ mod tests {
.unwrap(),
None,
),
(
StoreLimitsInputBuilder::default()
.max_triple_byte_size(150u128)
.build()
.unwrap(),
Some(ContractError::from(StoreError::MaxTripleByteSize(
176u128.into(),
150u128.into(),
))),
),
(
StoreLimitsInputBuilder::default()
.max_triple_byte_size(400u128)
.build()
.unwrap(),
None,
),
(
StoreLimitsInputBuilder::default()
.max_insert_data_triple_count(30u128)
Expand All @@ -288,8 +316,9 @@ mod tests {
),
];

let exec_msg = ExecuteMsg::InsertData {
input: DataInput::RDFXml(read_test_data("sample.rdf.xml")),
let exec_msg = InsertData {
format: Some(DataFormat::RDFXml),
data: read_test_data("sample.rdf.xml"),
};
for case in cases {
let mut deps = mock_dependencies();
Expand Down
3 changes: 2 additions & 1 deletion contracts/okp4-cognitarium/src/state/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ impl From<StoreLimits> for msg::StoreLimits {

#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
pub struct StoreStat {
pub triples_count: Uint128,
pub triple_count: Uint128,
pub byte_size: Uint128,
}
82 changes: 73 additions & 9 deletions contracts/okp4-cognitarium/src/state/storer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{rdf, ContractError};
use blake3::Hash;
use cosmwasm_std::{StdError, StdResult, Storage, Uint128};
use rio_api::model;
use rio_api::model::Term;
use std::collections::BTreeMap;
use std::io::BufRead;

Expand All @@ -17,6 +18,7 @@ pub struct TripleStorer<'a> {
ns_key_inc_offset: u128,
ns_cache: BTreeMap<String, Namespace>,
initial_triple_count: Uint128,
initial_byte_size: Uint128,
}

impl<'a> TripleStorer<'a> {
Expand All @@ -28,7 +30,8 @@ impl<'a> TripleStorer<'a> {
store: store.clone(),
ns_key_inc_offset,
ns_cache: BTreeMap::new(),
initial_triple_count: store.stat.triples_count,
initial_triple_count: store.stat.triple_count,
initial_byte_size: store.stat.byte_size,
})
}

Expand All @@ -41,15 +44,41 @@ impl<'a> TripleStorer<'a> {
}

pub fn store_triple(&mut self, t: model::Triple) -> Result<(), ContractError> {
let triple = self.triple(t)?;
self.store.stat.triples_count += Uint128::one();

if self.store.stat.triples_count > self.store.limits.max_triple_count {
self.store.stat.triple_count += Uint128::one();
if self.store.stat.triple_count > self.store.limits.max_triple_count {
Err(StoreError::MaxTriplesLimitExceeded(
self.store.limits.max_triple_count,
))?
}
if self.store.stat.triple_count - self.initial_triple_count
> self.store.limits.max_insert_data_triple_count
{
Err(StoreError::MaxInsertDataTripleCount(
self.store.limits.max_insert_data_triple_count,
))?
}

let t_size = Uint128::from(Self::triple_size(t) as u128);
if t_size > self.store.limits.max_triple_byte_size {
Err(StoreError::MaxTripleByteSize(
t_size,
self.store.limits.max_triple_byte_size,
))?
}

self.store.stat.byte_size += t_size;
if self.store.stat.byte_size > self.store.limits.max_byte_size {
Err(StoreError::MaxByteSize(self.store.limits.max_byte_size))?
}
if self.store.stat.byte_size - self.initial_byte_size
> self.store.limits.max_insert_data_byte_size
{
Err(StoreError::MaxInsertDataByteSize(
self.store.limits.max_insert_data_byte_size,
))?
}

let triple = self.triple(t)?;
let object_hash: Hash = triple.object.as_hash();
triples()
.save(
Expand All @@ -71,7 +100,7 @@ impl<'a> TripleStorer<'a> {
namespaces().save(self.storage, entry.0.to_string(), entry.1)?;
}

Ok(self.store.stat.triples_count - self.initial_triple_count)
Ok(self.store.stat.triple_count - self.initial_triple_count)
}

fn resolve_namespace_key(&mut self, ns_str: String) -> StdResult<u128> {
Expand Down Expand Up @@ -127,9 +156,9 @@ impl<'a> TripleStorer<'a> {

fn object(&mut self, object: model::Term) -> StdResult<Object> {
match object {
model::Term::BlankNode(node) => Ok(Object::Blank(node.id.to_string())),
model::Term::NamedNode(node) => self.node(node).map(|n| Object::Named(n)),
model::Term::Literal(literal) => self.literal(literal).map(|l| Object::Literal(l)),
Term::BlankNode(node) => Ok(Object::Blank(node.id.to_string())),
Term::NamedNode(node) => self.node(node).map(|n| Object::Named(n)),
Term::Literal(literal) => self.literal(literal).map(|l| Object::Literal(l)),
_ => Err(StdError::generic_err("RDF star syntax unsupported")),
}
}
Expand All @@ -151,4 +180,39 @@ impl<'a> TripleStorer<'a> {
}
}
}

fn triple_size(triple: model::Triple) -> usize {
Self::subject_size(triple.subject)
+ Self::node_size(triple.predicate)
+ Self::object_size(triple.object)
}

fn subject_size(subject: model::Subject) -> usize {
match subject {
model::Subject::NamedNode(n) => Self::node_size(n),
model::Subject::BlankNode(n) => n.id.len(),
model::Subject::Triple(_) => 0,
}
}

fn node_size(node: model::NamedNode) -> usize {
node.iri.len()
}

fn object_size(term: Term) -> usize {
match term {
Term::NamedNode(n) => Self::node_size(n),
Term::BlankNode(n) => n.id.len(),
Term::Literal(l) => match l {
model::Literal::Simple { value } => value.len(),
model::Literal::LanguageTaggedString { value, language } => {
value.len() + language.len()
}
model::Literal::Typed { value, datatype } => {
value.len() + Self::node_size(datatype)
}
},
Term::Triple(_) => 0,
}
}
}

0 comments on commit c10cf6a

Please sign in to comment.