Convert src/ to failure.

This commit is contained in:
Grisha Kruglov 2018-06-04 18:07:09 -04:00 committed by Nick Alexander
parent 836fdb3a35
commit 4e01929334
11 changed files with 131 additions and 197 deletions

View file

@ -28,7 +28,8 @@ rustc_version = "0.2"
[dependencies]
chrono = "0.4"
error-chain = { git = "https://github.com/rnewman/error-chain", branch = "rnewman/sync" }
failure = "0.1.1"
failure_derive = "0.1.1"
lazy_static = "0.2"
time = "0.1"
uuid = { version = "0.5", features = ["v4", "serde"] }

View file

@ -93,7 +93,10 @@ use entity_builder::{
TermBuilder,
};
use errors::*;
use errors::{
Result,
MentatError,
};
use query::{
Known,
@ -474,7 +477,7 @@ impl<'a, 'c> InProgress<'a, 'c> {
// Retrying is tracked by https://github.com/mozilla/mentat/issues/357.
// This should not occur -- an attempt to take a competing IMMEDIATE transaction
// will fail with `SQLITE_BUSY`, causing this function to abort.
bail!("Lost the transact() race!");
bail!(MentatError::UnexpectedLostTransactRace);
}
// Commit the SQLite transaction while we hold the mutex.
@ -506,7 +509,7 @@ impl<'a, 'c> InProgress<'a, 'c> {
cache_action: CacheAction) -> Result<()> {
let attribute_entid: Entid = self.schema
.attribute_for_ident(&attribute)
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.to_string()))?.1.into();
.ok_or_else(|| MentatError::UnknownAttribute(attribute.to_string()))?.1.into();
match cache_action {
CacheAction::Register => {
@ -579,17 +582,16 @@ impl Conn {
/// Prepare the provided SQLite handle for use as a Mentat store. Creates tables but
/// _does not_ write the bootstrap schema. This constructor should only be used by
/// consumers that expect to populate raw transaction data themselves.
pub(crate) fn empty(sqlite: &mut rusqlite::Connection) -> Result<Conn> {
let (tx, db) = db::create_empty_current_version(sqlite)
.chain_err(|| "Unable to initialize Mentat store")?;
let (tx, db) = db::create_empty_current_version(sqlite)?;
tx.commit()?;
Ok(Conn::new(db.partition_map, db.schema))
}
pub fn connect(sqlite: &mut rusqlite::Connection) -> Result<Conn> {
let db = db::ensure_current_version(sqlite)
.chain_err(|| "Unable to initialize Mentat store")?;
let db = db::ensure_current_version(sqlite)?;
Ok(Conn::new(db.partition_map, db.schema))
}
@ -801,7 +803,7 @@ impl Conn {
{
attribute_entid = metadata.schema
.attribute_for_ident(&attribute)
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.to_string()))?.1.into();
.ok_or_else(|| MentatError::UnknownAttribute(attribute.to_string()))?.1.into();
}
let cache = &mut metadata.attribute_cache;
@ -869,11 +871,11 @@ mod tests {
.partition_map[":db.part/user"].index;
let t = format!("[[:db/add {} :db.schema/attribute \"tempid\"]]", next + 1);
match conn.transact(&mut sqlite, t.as_str()).unwrap_err() {
Error(ErrorKind::DbError(::mentat_db::errors::ErrorKind::UnrecognizedEntid(e)), _) => {
match conn.transact(&mut sqlite, t.as_str()).expect_err("expected transact error").downcast() {
Ok(::mentat_db::DbError::UnrecognizedEntid(e)) => {
assert_eq!(e, next + 1);
},
x => panic!("expected transact error, got {:?}", x),
x => panic!("expected db error, got {:?}", x),
}
// Transact two more tempids.
@ -896,12 +898,12 @@ mod tests {
// we should reject this, because the first ID was provided by the user!
let t = format!("[[:db/add {} :db.schema/attribute \"tempid\"]]", next);
match conn.transact(&mut sqlite, t.as_str()).unwrap_err() {
Error(ErrorKind::DbError(::mentat_db::errors::ErrorKind::UnrecognizedEntid(e)), _) => {
match conn.transact(&mut sqlite, t.as_str()).expect_err("expected transact error").downcast() {
Ok(::mentat_db::DbError::UnrecognizedEntid(e)) => {
// All this, despite this being the ID we were about to allocate!
assert_eq!(e, next);
},
x => panic!("expected transact error, got {:?}", x),
x => panic!("expected db error, got {:?}", x),
}
// And if we subsequently transact in a way that allocates one ID, we _will_ use that one.
@ -1057,9 +1059,9 @@ mod tests {
// Bad EDN: missing closing ']'.
let report = conn.transact(&mut sqlite, "[[:db/add \"t\" :db/ident :a/keyword]");
match report.unwrap_err() {
Error(ErrorKind::EdnParseError(_), _) => { },
x => panic!("expected EDN parse error, got {:?}", x),
match report.expect_err("expected transact to fail for bad edn").downcast() {
Ok(edn::ParseError { .. }) => { },
Err(x) => panic!("expected EDN parse error, got {:?}", x),
}
// Good EDN.
@ -1068,9 +1070,9 @@ mod tests {
// Bad transaction data: missing leading :db/add.
let report = conn.transact(&mut sqlite, "[[\"t\" :db/ident :b/keyword]]");
match report.unwrap_err() {
Error(ErrorKind::EdnParseError(_), _) => { },
x => panic!("expected EDN parse error, got {:?}", x),
match report.expect_err("expected transact error").downcast() {
Ok(edn::ParseError { .. }) => { },
Err(x) => panic!("expected EDN parse error, got {:?}", x),
}
// Good transaction data.
@ -1080,8 +1082,8 @@ mod tests {
// Bad transaction based on state of store: conflicting upsert.
let report = conn.transact(&mut sqlite, "[[:db/add \"u\" :db/ident :a/keyword]
[:db/add \"u\" :db/ident :b/keyword]]");
match report.unwrap_err() {
Error(ErrorKind::DbError(::mentat_db::errors::ErrorKind::SchemaConstraintViolation(_)), _) => { },
match report.expect_err("expected transact error").downcast() {
Ok(::mentat_db::DbError::SchemaConstraintViolation(_)) => { },
x => panic!("expected schema constraint violation, got {:?}", x),
}
}
@ -1099,8 +1101,8 @@ mod tests {
let kw = kw!(:foo/bat);
let schema = conn.current_schema();
let res = conn.cache(&mut sqlite, &schema, &kw, CacheDirection::Forward, CacheAction::Register);
match res.unwrap_err() {
Error(ErrorKind::UnknownAttribute(msg), _) => assert_eq!(msg, ":foo/bat"),
match res.expect_err("expected cache to fail").downcast() {
Ok(MentatError::UnknownAttribute(msg)) => assert_eq!(msg, ":foo/bat"),
x => panic!("expected UnknownAttribute error, got {:?}", x),
}
}

View file

@ -85,7 +85,7 @@ use conn::{
};
use errors::{
ErrorKind,
MentatError,
Result,
};
@ -277,12 +277,12 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> {
let provided = tv.value_type();
let expected = attr.value_type;
if provided != expected {
bail!(ErrorKind::ValueTypeMismatch(provided, expected));
bail!(MentatError::ValueTypeMismatch(provided, expected));
}
}
attribute = aa;
} else {
bail!(ErrorKind::UnknownAttribute(a.to_string()));
bail!(MentatError::UnknownAttribute(a.to_string()));
}
Ok((attribute, v))
}
@ -380,11 +380,6 @@ impl FromThing<KnownEntid> for TypedValueOr<TempIdHandle> {
mod testing {
extern crate mentat_db;
use errors::{
Error,
ErrorKind,
};
// For matching inside a test.
use mentat_db::ErrorKind::{
UnrecognizedEntid,
@ -429,7 +424,7 @@ mod testing {
let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully");
// This should fail: unrecognized entid.
if let Err(Error(ErrorKind::DbError(UnrecognizedEntid(e)), _)) = in_progress.transact_terms(terms, tempids) {
if let Err(Error(MentatError::DbError(UnrecognizedEntid(e)), _)) = in_progress.transact_terms(terms, tempids) {
assert_eq!(e, 999);
} else {
panic!("Should have rejected the entid.");

View file

@ -10,102 +10,63 @@
#![allow(dead_code)]
use rusqlite;
use uuid;
use std; // To refer to std::result::Result.
use std::collections::BTreeSet;
use edn;
use failure::Error;
use mentat_core::{
Attribute,
ValueType,
};
use mentat_db;
use mentat_query;
use mentat_query_algebrizer;
use mentat_query_projector;
use mentat_query_pull;
use mentat_query_translator;
use mentat_sql;
use mentat_tolstoy;
error_chain! {
types {
Error, ErrorKind, ResultExt, Result;
}
pub type Result<T> = std::result::Result<T, Error>;
foreign_links {
EdnParseError(edn::ParseError);
Rusqlite(rusqlite::Error);
UuidParseError(uuid::ParseError);
IoError(::std::io::Error);
}
links {
DbError(mentat_db::Error, mentat_db::ErrorKind);
QueryError(mentat_query_algebrizer::Error, mentat_query_algebrizer::ErrorKind); // Let's not leak the term 'algebrizer'.
ProjectorError(mentat_query_projector::errors::Error, mentat_query_projector::errors::ErrorKind);
PullError(mentat_query_pull::errors::Error, mentat_query_pull::errors::ErrorKind);
TranslatorError(mentat_query_translator::Error, mentat_query_translator::ErrorKind);
SqlError(mentat_sql::Error, mentat_sql::ErrorKind);
SyncError(mentat_tolstoy::Error, mentat_tolstoy::ErrorKind);
}
errors {
PathAlreadyExists(path: String) {
description("path already exists")
display("path {} already exists", path)
}
UnboundVariables(names: BTreeSet<String>) {
description("unbound variables at query execution time")
display("variables {:?} unbound at query execution time", names)
}
InvalidArgumentName(name: String) {
description("invalid argument name")
display("invalid argument name: '{}'", name)
}
UnknownAttribute(name: String) {
description("unknown attribute")
display("unknown attribute: '{}'", name)
}
InvalidVocabularyVersion {
description("invalid vocabulary version")
display("invalid vocabulary version")
}
ConflictingAttributeDefinitions(vocabulary: String, version: ::vocabulary::Version, attribute: String, current: Attribute, requested: Attribute) {
description("conflicting attribute definitions")
display("vocabulary {}/{} already has attribute {}, and the requested definition differs", vocabulary, version, attribute)
}
ExistingVocabularyTooNew(name: String, existing: ::vocabulary::Version, ours: ::vocabulary::Version) {
description("existing vocabulary too new")
display("existing vocabulary too new: wanted {}, got {}", ours, existing)
}
UnexpectedCoreSchema(version: Option<::vocabulary::Version>) {
description("unexpected core schema version")
display("core schema: wanted {}, got {:?}", mentat_db::CORE_SCHEMA_VERSION, version)
}
MissingCoreVocabulary(kw: mentat_query::Keyword) {
description("missing core vocabulary")
display("missing core attribute {}", kw)
}
PreparedQuerySchemaMismatch {
description("schema changed since query was prepared")
display("schema changed since query was prepared")
}
ValueTypeMismatch(provided: ValueType, expected: ValueType) {
description("provided value doesn't match value type")
display("provided value of type {} doesn't match attribute value type {}", provided, expected)
}
}
#[macro_export]
macro_rules! bail {
($e:expr) => (
return Err($e.into());
)
}
#[derive(Debug, Fail)]
pub enum MentatError {
#[fail(display = "path {} already exists", _0)]
PathAlreadyExists(String),
#[fail(display = "variables {:?} unbound at query execution time", _0)]
UnboundVariables(BTreeSet<String>),
#[fail(display = "invalid argument name: '{}'", _0)]
InvalidArgumentName(String),
#[fail(display = "unknown attribute: '{}'", _0)]
UnknownAttribute(String),
#[fail(display = "invalid vocabulary version")]
InvalidVocabularyVersion,
#[fail(display = "vocabulary {}/{} already has attribute {}, and the requested definition differs", _0, _1, _2)]
ConflictingAttributeDefinitions(String, ::vocabulary::Version, String, Attribute, Attribute),
#[fail(display = "existing vocabulary {} too new: wanted {}, got {}", _0, _1, _2)]
ExistingVocabularyTooNew(String, ::vocabulary::Version, ::vocabulary::Version),
#[fail(display = "core schema: wanted {}, got {:?}", _0, _1)]
UnexpectedCoreSchema(::vocabulary::Version, Option<::vocabulary::Version>),
#[fail(display = "Lost the transact() race!")]
UnexpectedLostTransactRace,
#[fail(display = "missing core attribute {}", _0)]
MissingCoreVocabulary(mentat_query::Keyword),
#[fail(display = "schema changed since query was prepared")]
PreparedQuerySchemaMismatch,
#[fail(display = "provided value of type {} doesn't match attribute value type {}", _0, _1)]
ValueTypeMismatch(ValueType, ValueType),
}

View file

@ -11,7 +11,8 @@
#![recursion_limit="128"]
#[macro_use]
extern crate error_chain;
extern crate failure_derive;
extern crate failure;
#[macro_use]
extern crate lazy_static;
@ -101,9 +102,10 @@ macro_rules! kw {
};
}
#[macro_use]
pub mod errors;
pub mod conn;
pub mod entity_builder;
pub mod errors;
pub mod ident;
pub mod query;
pub mod query_builder;

View file

@ -74,7 +74,7 @@ pub use mentat_query_projector::{
};
use errors::{
ErrorKind,
MentatError,
Result,
};
@ -178,7 +178,7 @@ fn algebrize_query<T>
// If they aren't, the user has made an error -- perhaps writing the wrong variable in `:in`, or
// not binding in the `QueryInput`.
if !unbound.is_empty() {
bail!(ErrorKind::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect()));
bail!(MentatError::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect()));
}
Ok(algebrized)
}
@ -211,7 +211,7 @@ fn fetch_values<'sqlite>
fn lookup_attribute(schema: &Schema, attribute: &Keyword) -> Result<KnownEntid> {
schema.get_entid(attribute)
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.name().into()).into())
.ok_or_else(|| MentatError::UnknownAttribute(attribute.name().into()).into())
}
/// Return a single value for the provided entity and attribute.
@ -398,7 +398,7 @@ pub fn q_prepare<'sqlite, 'schema, 'cache, 'query, T>
if !unbound.is_empty() {
// TODO: Allow binding variables at execution time, not just
// preparation time.
bail!(ErrorKind::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect()));
bail!(MentatError::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect()));
}
if algebrized.is_known_empty() {

View file

@ -34,7 +34,7 @@ use ::{
};
use errors::{
ErrorKind,
MentatError,
Result,
};
@ -56,7 +56,7 @@ impl<'a> QueryBuilder<'a> {
}
pub fn bind_ref_from_kw(&mut self, var: &str, value: Keyword) -> Result<&mut Self> {
let entid = self.store.conn().current_schema().get_entid(&value).ok_or(ErrorKind::UnknownAttribute(value.to_string()))?;
let entid = self.store.conn().current_schema().get_entid(&value).ok_or(MentatError::UnknownAttribute(value.to_string()))?;
self.values.insert(Variable::from_valid_name(var), TypedValue::Ref(entid.into()));
Ok(self)
}

View file

@ -84,7 +84,7 @@ impl Store {
pub fn open_empty(path: &str) -> Result<Store> {
if !path.is_empty() {
if Path::new(path).exists() {
bail!(ErrorKind::PathAlreadyExists(path.to_string()));
bail!(MentatError::PathAlreadyExists(path.to_string()));
}
}
@ -124,7 +124,7 @@ impl Store {
pub fn open_empty_with_key(path: &str, encryption_key: &str) -> Result<Store> {
if !path.is_empty() {
if Path::new(path).exists() {
bail!(ErrorKind::PathAlreadyExists(path.to_string()));
bail!(MentatError::PathAlreadyExists(path.to_string()));
}
}

View file

@ -121,7 +121,7 @@ use ::conn::{
};
use ::errors::{
ErrorKind,
MentatError,
Result,
};
@ -375,17 +375,17 @@ trait HasCoreSchema {
impl<T> HasCoreSchema for T where T: HasSchema {
fn core_type(&self, t: ValueType) -> Result<KnownEntid> {
self.entid_for_type(t)
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
.ok_or_else(|| MentatError::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
}
fn core_entid(&self, ident: &Keyword) -> Result<KnownEntid> {
self.get_entid(ident)
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
.ok_or_else(|| MentatError::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
}
fn core_attribute(&self, ident: &Keyword) -> Result<KnownEntid> {
self.attribute_for_ident(ident)
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
.ok_or_else(|| MentatError::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
.map(|(_, e)| e)
}
}
@ -568,7 +568,7 @@ pub trait VersionedStore: HasVocabularies + HasSchema {
// We have two vocabularies with the same name, same version, and
// different definitions for an attribute. That's a coding error.
// We can't accept this vocabulary.
bail!(ErrorKind::ConflictingAttributeDefinitions(
bail!(MentatError::ConflictingAttributeDefinitions(
definition.name.to_string(),
definition.version,
pair.0.to_string(),
@ -615,13 +615,13 @@ pub trait VersionedStore: HasVocabularies + HasSchema {
fn verify_core_schema(&self) -> Result<()> {
if let Some(core) = self.read_vocabulary_named(&DB_SCHEMA_CORE)? {
if core.version != CORE_SCHEMA_VERSION {
bail!(ErrorKind::UnexpectedCoreSchema(Some(core.version)));
bail!(MentatError::UnexpectedCoreSchema(CORE_SCHEMA_VERSION, Some(core.version)));
}
// TODO: check things other than the version.
} else {
// This would be seriously messed up.
bail!(ErrorKind::UnexpectedCoreSchema(None));
bail!(MentatError::UnexpectedCoreSchema(CORE_SCHEMA_VERSION, None));
}
Ok(())
}
@ -682,7 +682,7 @@ impl<'a, 'c> VersionedStore for InProgress<'a, 'c> {
VocabularyCheck::NotPresent => self.install_vocabulary(definition),
VocabularyCheck::PresentButNeedsUpdate { older_version } => self.upgrade_vocabulary(definition, older_version),
VocabularyCheck::PresentButMissingAttributes { attributes } => self.install_attributes_for(definition, attributes),
VocabularyCheck::PresentButTooNew { newer_version } => Err(ErrorKind::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version).into()),
VocabularyCheck::PresentButTooNew { newer_version } => Err(MentatError::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version).into()),
}
}
@ -701,7 +701,7 @@ impl<'a, 'c> VersionedStore for InProgress<'a, 'c> {
out.insert(definition.name.clone(), VocabularyOutcome::Existed);
},
VocabularyCheck::PresentButTooNew { newer_version } => {
bail!(ErrorKind::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version));
bail!(MentatError::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version));
},
c @ VocabularyCheck::NotPresent |
@ -868,7 +868,7 @@ impl<T> HasVocabularies for T where T: HasSchema + Queryable {
attributes: attributes,
}))
},
Some(_) => bail!(ErrorKind::InvalidVocabularyVersion),
Some(_) => bail!(MentatError::InvalidVocabularyVersion),
}
} else {
Ok(None)

View file

@ -61,8 +61,7 @@ use mentat::query::q_uncached;
use mentat::conn::Conn;
use mentat::errors::{
Error,
ErrorKind,
MentatError,
};
#[test]
@ -234,11 +233,11 @@ fn test_unbound_inputs() {
let results = q_uncached(&c, &db.schema,
"[:find ?i . :in ?e :where [?e :db/ident ?i]]", inputs);
match results {
Result::Err(Error(ErrorKind::UnboundVariables(vars), _)) => {
match results.expect_err("expected unbound variables").downcast().expect("expected specific error") {
MentatError::UnboundVariables(vars) => {
assert_eq!(vars, vec!["?e".to_string()].into_iter().collect());
},
_ => panic!("Expected unbound variables."),
_ => panic!("Expected UnboundVariables variant."),
}
}
@ -412,8 +411,8 @@ fn test_fulltext() {
[?a :foo/term ?term]
]"#;
let r = conn.q_once(&mut c, query, None);
match r {
Err(Error(ErrorKind::QueryError(mentat_query_algebrizer::ErrorKind::InvalidArgument(PlainSymbol(s), ty, i)), _)) => {
match r.expect_err("expected query to fail").downcast() {
Ok(mentat_query_algebrizer::AlgebrizerError::InvalidArgument(PlainSymbol(s), ty, i)) => {
assert_eq!(s, "fulltext");
assert_eq!(ty, "string");
assert_eq!(i, 2);
@ -427,8 +426,8 @@ fn test_fulltext() {
[?a :foo/term ?term]
[(fulltext $ :foo/fts ?a) [[?x ?val]]]]"#;
let r = conn.q_once(&mut c, query, None);
match r {
Err(Error(ErrorKind::QueryError(mentat_query_algebrizer::ErrorKind::InvalidArgument(PlainSymbol(s), ty, i)), _)) => {
match r.expect_err("expected query to fail").downcast() {
Ok(mentat_query_algebrizer::AlgebrizerError::InvalidArgument(PlainSymbol(s), ty, i)) => {
assert_eq!(s, "fulltext");
assert_eq!(ty, "string");
assert_eq!(i, 2);
@ -583,42 +582,25 @@ fn test_aggregates_type_handling() {
// No type limits => can't do it.
let r = store.q_once(r#"[:find (sum ?v) . :where [_ _ ?v]]"#, None);
let all_types = ValueTypeSet::any();
match r {
Result::Err(
Error(
ErrorKind::TranslatorError(
::mentat_query_translator::ErrorKind::ProjectorError(
::mentat_query_projector::errors::ErrorKind::CannotApplyAggregateOperationToTypes(
SimpleAggregationOp::Sum,
types
),
)
),
_)) => {
assert_eq!(types, all_types);
},
r => panic!("Unexpected: {:?}", r),
match r.expect_err("expected query to fail").downcast() {
Ok(::mentat_query_projector::errors::ProjectorError::CannotApplyAggregateOperationToTypes(
SimpleAggregationOp::Sum, types)) => {
assert_eq!(types, all_types);
},
e => panic!("Unexpected error type {:?}", e),
}
// You can't sum instants.
let r = store.q_once(r#"[:find (sum ?v) .
:where [_ _ ?v] [(type ?v :db.type/instant)]]"#,
None);
match r {
Result::Err(
Error(
ErrorKind::TranslatorError(
::mentat_query_translator::ErrorKind::ProjectorError(
::mentat_query_projector::errors::ErrorKind::CannotApplyAggregateOperationToTypes(
SimpleAggregationOp::Sum,
types
),
)
),
_)) => {
assert_eq!(types, ValueTypeSet::of_one(ValueType::Instant));
},
r => panic!("Unexpected: {:?}", r),
match r.expect_err("expected query to fail").downcast() {
Ok(::mentat_query_projector::errors::ProjectorError::CannotApplyAggregateOperationToTypes(
SimpleAggregationOp::Sum,
types)) => {
assert_eq!(types, ValueTypeSet::of_one(ValueType::Instant));
},
e => panic!("Unexpected error type {:?}", e),
}
// But you can count them.
@ -1354,19 +1336,13 @@ fn test_aggregation_implicit_grouping() {
[?person :foo/play ?game]
[?person :foo/is-vegetarian true]
[?person :foo/name ?name]]"#, None);
match res {
Result::Err(
Error(
ErrorKind::TranslatorError(
::mentat_query_translator::ErrorKind::ProjectorError(
::mentat_query_projector::errors::ErrorKind::AmbiguousAggregates(mmc, cc)
)
), _)) => {
match res.expect_err("expected query to fail").downcast() {
Ok(::mentat_query_projector::errors::ProjectorError::AmbiguousAggregates(mmc, cc)) => {
assert_eq!(mmc, 2);
assert_eq!(cc, 1);
},
r => {
panic!("Unexpected result {:?}.", r);
e => {
panic!("Unexpected error type {:?}.", e);
},
}

View file

@ -59,10 +59,7 @@ use mentat::entity_builder::{
TermBuilder,
};
use mentat::errors::{
Error,
ErrorKind,
};
use mentat::errors::MentatError;
lazy_static! {
static ref FOO_NAME: Keyword = {
@ -289,8 +286,8 @@ fn test_add_vocab() {
// Scoped borrow of `conn`.
{
let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully");
match in_progress.ensure_vocabulary(&foo_v1_malformed) {
Result::Err(Error(ErrorKind::ConflictingAttributeDefinitions(vocab, version, attr, theirs, ours), _)) => {
match in_progress.ensure_vocabulary(&foo_v1_malformed).expect_err("expected vocabulary to fail").downcast() {
Ok(MentatError::ConflictingAttributeDefinitions(vocab, version, attr, theirs, ours)) => {
assert_eq!(vocab.as_str(), ":org.mozilla/foo");
assert_eq!(attr.as_str(), ":foo/baz");
assert_eq!(version, 1);