diff --git a/Cargo.toml b/Cargo.toml index 33d49058..93ee9ca6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/src/conn.rs b/src/conn.rs index 894de855..be872a88 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -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 { - 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 { - 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), } } diff --git a/src/entity_builder.rs b/src/entity_builder.rs index 263ed604..ffa1f56a 100644 --- a/src/entity_builder.rs +++ b/src/entity_builder.rs @@ -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 for TypedValueOr { 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."); diff --git a/src/errors.rs b/src/errors.rs index 126faa00..29622c5c 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -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 = std::result::Result; - 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) { - 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), + + #[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), } diff --git a/src/lib.rs b/src/lib.rs index 3fb6b575..b3a657e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/query.rs b/src/query.rs index 77322472..16fa3e3f 100644 --- a/src/query.rs +++ b/src/query.rs @@ -74,7 +74,7 @@ pub use mentat_query_projector::{ }; use errors::{ - ErrorKind, + MentatError, Result, }; @@ -178,7 +178,7 @@ fn algebrize_query // 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 { 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() { diff --git a/src/query_builder.rs b/src/query_builder.rs index bafc59e7..6be1d2e0 100644 --- a/src/query_builder.rs +++ b/src/query_builder.rs @@ -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) } diff --git a/src/store.rs b/src/store.rs index 0fd106f8..30856683 100644 --- a/src/store.rs +++ b/src/store.rs @@ -84,7 +84,7 @@ impl Store { pub fn open_empty(path: &str) -> Result { 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 { if !path.is_empty() { if Path::new(path).exists() { - bail!(ErrorKind::PathAlreadyExists(path.to_string())); + bail!(MentatError::PathAlreadyExists(path.to_string())); } } diff --git a/src/vocabulary.rs b/src/vocabulary.rs index f17a3812..7e622ee2 100644 --- a/src/vocabulary.rs +++ b/src/vocabulary.rs @@ -121,7 +121,7 @@ use ::conn::{ }; use ::errors::{ - ErrorKind, + MentatError, Result, }; @@ -375,17 +375,17 @@ trait HasCoreSchema { impl HasCoreSchema for T where T: HasSchema { fn core_type(&self, t: ValueType) -> Result { 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 { 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 { 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 HasVocabularies for T where T: HasSchema + Queryable { attributes: attributes, })) }, - Some(_) => bail!(ErrorKind::InvalidVocabularyVersion), + Some(_) => bail!(MentatError::InvalidVocabularyVersion), } } else { Ok(None) diff --git a/tests/query.rs b/tests/query.rs index 6b7d2a48..8b3b012e 100644 --- a/tests/query.rs +++ b/tests/query.rs @@ -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); }, } diff --git a/tests/vocabulary.rs b/tests/vocabulary.rs index 46dd4c1f..9e4841d2 100644 --- a/tests/vocabulary.rs +++ b/tests/vocabulary.rs @@ -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);