From 1a9aea84c19b08f0813146d4f0c671eaab4cee64 Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Tue, 5 Aug 2025 19:32:34 -0400 Subject: [PATCH] linter: simplify tests --- .vscode/linter.code-snippets | 4 +- crates/squawk_linter/src/lib.rs | 14 +- .../src/rules/adding_field_with_default.rs | 59 ++------ .../rules/adding_foreign_key_constraint.rs | 19 +-- .../src/rules/adding_not_null_field.rs | 23 +-- .../rules/adding_primary_key_constraint.rs | 15 +- .../src/rules/adding_required_field.rs | 23 +-- .../ban_alter_domain_with_add_constraint.rs | 11 +- .../squawk_linter/src/rules/ban_char_field.rs | 23 +-- ...oncurrent_index_creation_in_transaction.rs | 25 +--- .../ban_create_domain_with_constraint.rs | 15 +- .../src/rules/ban_drop_column.rs | 7 +- .../src/rules/ban_drop_database.rs | 7 +- .../src/rules/ban_drop_not_null.rs | 7 +- .../squawk_linter/src/rules/ban_drop_table.rs | 7 +- .../src/rules/ban_truncate_cascade.rs | 12 +- .../src/rules/changing_column_type.rs | 11 +- .../src/rules/constraint_missing_not_valid.rs | 51 ++----- .../src/rules/disallow_unique_constraint.rs | 35 ++--- .../src/rules/prefer_bigint_over_int.rs | 11 +- .../src/rules/prefer_bigint_over_smallint.rs | 11 +- .../src/rules/prefer_identity.rs | 15 +- .../src/rules/prefer_robust_stmts.rs | 137 +++++------------- .../src/rules/prefer_text_field.rs | 27 +--- .../src/rules/prefer_timestamptz.rs | 19 +-- .../src/rules/renaming_column.rs | 7 +- .../squawk_linter/src/rules/renaming_table.rs | 7 +- .../require_concurrent_index_creation.rs | 19 +-- .../require_concurrent_index_deletion.rs | 23 +-- ...tmts__test__double_add_after_drop_err.snap | 4 +- crates/squawk_linter/src/test_utils.rs | 16 ++ crates/squawk_linter/src/version.rs | 6 + 32 files changed, 214 insertions(+), 456 deletions(-) create mode 100644 crates/squawk_linter/src/test_utils.rs diff --git a/.vscode/linter.code-snippets b/.vscode/linter.code-snippets index 63b32251..3a10fa79 100644 --- a/.vscode/linter.code-snippets +++ b/.vscode/linter.code-snippets @@ -26,9 +26,7 @@ "$2", " \"#;", "", -" let file = SourceFile::parse(&sql);", -" let mut linter = Linter::new([Rule::$3]);", -" let errors = linter.lint(file, sql);", +" let errors = lint(sql, Rule::$3);", " assert_debug_snapshot!(errors);", "}", diff --git a/crates/squawk_linter/src/lib.rs b/crates/squawk_linter/src/lib.rs index 558f8060..ba51fce9 100644 --- a/crates/squawk_linter/src/lib.rs +++ b/crates/squawk_linter/src/lib.rs @@ -6,7 +6,6 @@ use enum_iterator::all; pub use ignore::Ignore; use ignore::find_ignores; use ignore_index::IgnoreIndex; -use lazy_static::lazy_static; use rowan::TextRange; use rowan::TextSize; use serde::{Deserialize, Serialize}; @@ -22,6 +21,9 @@ mod visitors; mod identifier; mod rules; + +#[cfg(test)] +mod test_utils; use rules::adding_field_with_default; use rules::adding_foreign_key_constraint; use rules::adding_not_null_field; @@ -278,15 +280,12 @@ impl Violation { } } +#[derive(Default)] pub struct LinterSettings { pub pg_version: Version, pub assume_in_transaction: bool, } -lazy_static! { - static ref DEFAULT_PG_VERSION: Version = Version::new(15, 0, 0); -} - pub struct Linter { errors: Vec, ignores: Vec, @@ -440,10 +439,7 @@ impl Linter { errors: vec![], ignores: vec![], rules: rules.into(), - settings: LinterSettings { - pg_version: *DEFAULT_PG_VERSION, - assume_in_transaction: false, - }, + settings: LinterSettings::default(), } } } diff --git a/crates/squawk_linter/src/rules/adding_field_with_default.rs b/crates/squawk_linter/src/rules/adding_field_with_default.rs index 01f676a6..beb1f549 100644 --- a/crates/squawk_linter/src/rules/adding_field_with_default.rs +++ b/crates/squawk_linter/src/rules/adding_field_with_default.rs @@ -101,7 +101,8 @@ pub(crate) fn adding_field_with_default(ctx: &mut Linter, parse: &Parse) mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn set_not_null() { let sql = r#" ALTER TABLE "core_recipe" ALTER COLUMN "foo" SET NOT NULL; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::AddingNotNullableField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::AddingNotNullableField); assert!(!errors.is_empty()); assert_debug_snapshot!(errors); } @@ -59,9 +58,7 @@ ALTER TABLE "core_recipe" ADD COLUMN "foo" integer DEFAULT 10 NOT NULL; ALTER TABLE "core_recipe" ALTER COLUMN "foo" DROP DEFAULT; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::AddingNotNullableField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::AddingNotNullableField); assert!(errors.is_empty()); } @@ -71,9 +68,7 @@ COMMIT; -- This won't work if the table is populated, but that error is caught by adding-required-field. ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::AddingNotNullableField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::AddingNotNullableField); assert!(errors.is_empty()); } @@ -87,9 +82,7 @@ BEGIN; ALTER TABLE "core_recipe" ADD COLUMN "foo" integer NOT NULL DEFAULT 10; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::AddingNotNullableField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::AddingNotNullableField); assert!(errors.is_empty()); } @@ -102,9 +95,7 @@ ALTER TABLE my_table ALTER COLUMN my_column SET NOT NULL; UPDATE alembic_version SET version_num='b' WHERE alembic_version.version_num = 'a'; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::AddingNotNullableField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::AddingNotNullableField); assert!(!errors.is_empty()); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/adding_primary_key_constraint.rs b/crates/squawk_linter/src/rules/adding_primary_key_constraint.rs index 39fad5f0..bbd58bc3 100644 --- a/crates/squawk_linter/src/rules/adding_primary_key_constraint.rs +++ b/crates/squawk_linter/src/rules/adding_primary_key_constraint.rs @@ -54,16 +54,15 @@ pub(crate) fn adding_primary_key_constraint(ctx: &mut Linter, parse: &Parse 0); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanAlterDomainWithAddConstraint]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanAlterDomainWithAddConstraint); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -52,9 +51,7 @@ mod test { ALTER DOMAIN domain_name_7 OWNER TO you; ALTER DOMAIN domain_name_8 SET SCHEMA foo; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanAlterDomainWithAddConstraint]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanAlterDomainWithAddConstraint); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/ban_char_field.rs b/crates/squawk_linter/src/rules/ban_char_field.rs index 788497e6..6677274a 100644 --- a/crates/squawk_linter/src/rules/ban_char_field.rs +++ b/crates/squawk_linter/src/rules/ban_char_field.rs @@ -71,7 +71,8 @@ pub(crate) fn ban_char_field(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn creating_table_with_char_errors() { @@ -84,9 +85,7 @@ CREATE TABLE "core_bar" ( "delta" character NOT NULL ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCharField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCharField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -100,9 +99,7 @@ CREATE TABLE "core_bar" ( "beta" text NOT NULL ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCharField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCharField); assert_eq!(errors.len(), 0); } @@ -126,9 +123,7 @@ create table t ( p char[] ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCharField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCharField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -140,9 +135,7 @@ create table t ( a char[] ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCharField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCharField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -152,9 +145,7 @@ create table t ( let sql = r#" alter table t add column c char; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCharField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCharField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/ban_concurrent_index_creation_in_transaction.rs b/crates/squawk_linter/src/rules/ban_concurrent_index_creation_in_transaction.rs index 7fe09159..420b71fd 100644 --- a/crates/squawk_linter/src/rules/ban_concurrent_index_creation_in_transaction.rs +++ b/crates/squawk_linter/src/rules/ban_concurrent_index_creation_in_transaction.rs @@ -45,7 +45,7 @@ pub(crate) fn ban_concurrent_index_creation_in_transaction( mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::{Rule, test_utils::{lint, lint_with_assume_in_transaction}}; #[test] fn ban_concurrent_index_creation_in_transaction_err() { @@ -55,9 +55,7 @@ mod test { CREATE INDEX CONCURRENTLY "field_name_idx" ON "table_name" ("field_name"); COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanConcurrentIndexCreationInTransaction]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanConcurrentIndexCreationInTransaction); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -68,9 +66,7 @@ mod test { -- run outside a transaction CREATE INDEX CONCURRENTLY "field_name_idx" ON "table_name" ("field_name"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanConcurrentIndexCreationInTransaction]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanConcurrentIndexCreationInTransaction); assert_eq!(errors.len(), 0); } @@ -81,10 +77,7 @@ mod test { CREATE UNIQUE INDEX CONCURRENTLY "field_name_idx" ON "table_name" ("field_name"); ALTER TABLE "table_name" ADD CONSTRAINT "field_name_id" UNIQUE USING INDEX "field_name_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanConcurrentIndexCreationInTransaction]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::BanConcurrentIndexCreationInTransaction); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -95,10 +88,7 @@ mod test { -- run index creation in a standalone migration CREATE UNIQUE INDEX CONCURRENTLY "field_name_idx" ON "table_name" ("field_name"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanConcurrentIndexCreationInTransaction]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::BanConcurrentIndexCreationInTransaction); assert_eq!(errors.len(), 0); } @@ -111,10 +101,7 @@ mod test { BEGIN; ALTER TABLE "table_name" ADD CONSTRAINT "field_name_id" UNIQUE USING INDEX "field_name_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanConcurrentIndexCreationInTransaction]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::BanConcurrentIndexCreationInTransaction); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/ban_create_domain_with_constraint.rs b/crates/squawk_linter/src/rules/ban_create_domain_with_constraint.rs index 800d6fdc..0657fe88 100644 --- a/crates/squawk_linter/src/rules/ban_create_domain_with_constraint.rs +++ b/crates/squawk_linter/src/rules/ban_create_domain_with_constraint.rs @@ -38,16 +38,15 @@ pub(crate) fn ban_create_domain_with_constraint(ctx: &mut Linter, parse: &Parse< mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { let sql = r#" CREATE DOMAIN domain_name_3 AS NUMERIC(15,5) CHECK (value > 0); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCreateDomainWithConstraint]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCreateDomainWithConstraint); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -58,9 +57,7 @@ CREATE DOMAIN domain_name_3 AS NUMERIC(15,5) CHECK (value > 0); let sql = r#" create domain d as t check (value > 0) not null; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCreateDomainWithConstraint]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCreateDomainWithConstraint); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -72,9 +69,7 @@ create domain d as t check (value > 0) not null; CREATE DOMAIN domain_name_1 AS TEXT; CREATE DOMAIN domain_name_2 AS CHARACTER VARYING; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanCreateDomainWithConstraint]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanCreateDomainWithConstraint); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/ban_drop_column.rs b/crates/squawk_linter/src/rules/ban_drop_column.rs index 41875e21..a09a66f0 100644 --- a/crates/squawk_linter/src/rules/ban_drop_column.rs +++ b/crates/squawk_linter/src/rules/ban_drop_column.rs @@ -27,16 +27,15 @@ pub(crate) fn ban_drop_column(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { let sql = r#" ALTER TABLE "bar_tbl" DROP COLUMN "foo_col" CASCADE; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanDropColumn]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanDropColumn); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/ban_drop_database.rs b/crates/squawk_linter/src/rules/ban_drop_database.rs index 5adbe0bb..249e7b10 100644 --- a/crates/squawk_linter/src/rules/ban_drop_database.rs +++ b/crates/squawk_linter/src/rules/ban_drop_database.rs @@ -24,7 +24,8 @@ pub(crate) fn ban_drop_database(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn ban_drop_database() { @@ -33,9 +34,7 @@ mod test { DROP DATABASE IF EXISTS "table_name"; DROP DATABASE IF EXISTS "table_name" "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanDropDatabase]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanDropDatabase); assert!(!errors.is_empty()); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/ban_drop_not_null.rs b/crates/squawk_linter/src/rules/ban_drop_not_null.rs index 42ebc444..c146663a 100644 --- a/crates/squawk_linter/src/rules/ban_drop_not_null.rs +++ b/crates/squawk_linter/src/rules/ban_drop_not_null.rs @@ -31,16 +31,15 @@ pub(crate) fn ban_drop_not_null(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { let sql = r#" ALTER TABLE "bar_tbl" ALTER COLUMN "foo_col" DROP NOT NULL; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanDropNotNull]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanDropNotNull); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/ban_drop_table.rs b/crates/squawk_linter/src/rules/ban_drop_table.rs index 9acca17b..53cfa14c 100644 --- a/crates/squawk_linter/src/rules/ban_drop_table.rs +++ b/crates/squawk_linter/src/rules/ban_drop_table.rs @@ -23,7 +23,8 @@ pub(crate) fn ban_drop_table(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { @@ -32,9 +33,7 @@ DROP TABLE "table_name"; DROP TABLE IF EXISTS "table_name"; DROP TABLE IF EXISTS "table_name" "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanDropTable]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanDropTable); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/ban_truncate_cascade.rs b/crates/squawk_linter/src/rules/ban_truncate_cascade.rs index 30f26416..5b3abcdf 100644 --- a/crates/squawk_linter/src/rules/ban_truncate_cascade.rs +++ b/crates/squawk_linter/src/rules/ban_truncate_cascade.rs @@ -25,17 +25,15 @@ pub(crate) fn ban_truncate_cascade(ctx: &mut Linter, parse: &Parse) mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; - use squawk_syntax::SourceFile; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { let sql = r#" truncate a, b, c cascade; "#; - let file = SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanTruncateCascade]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanTruncateCascade); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -46,9 +44,7 @@ mod test { truncate a, b, c; truncate a; "#; - let file = SourceFile::parse(sql); - let mut linter = Linter::from([Rule::BanTruncateCascade]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::BanTruncateCascade); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/changing_column_type.rs b/crates/squawk_linter/src/rules/changing_column_type.rs index 0fb73f66..ac6ee562 100644 --- a/crates/squawk_linter/src/rules/changing_column_type.rs +++ b/crates/squawk_linter/src/rules/changing_column_type.rs @@ -29,7 +29,8 @@ pub(crate) fn changing_column_type(ctx: &mut Linter, parse: &Parse) mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { @@ -41,9 +42,7 @@ BEGIN; ALTER TABLE "core_recipe" ALTER COLUMN "edits" TYPE text USING "edits"::text; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ChangingColumnType]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::ChangingColumnType); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -59,9 +58,7 @@ ALTER TABLE "core_recipe" ALTER COLUMN "foo" TYPE varchar(255) USING "foo"::varc ALTER TABLE "core_recipe" ALTER COLUMN "foo" TYPE text USING "foo"::text; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ChangingColumnType]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::ChangingColumnType); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs b/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs index 12411b87..cb818452 100644 --- a/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs +++ b/crates/squawk_linter/src/rules/constraint_missing_not_valid.rs @@ -144,7 +144,7 @@ pub(crate) fn constraint_missing_not_valid(ctx: &mut Linter, parse: &Parse= 0); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ConstraintMissingNotValid]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::ConstraintMissingNotValid); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -237,9 +222,7 @@ ALTER TABLE "accounts" ADD CONSTRAINT "positive_balance" CHECK ("balance" >= 0); ALTER TABLE "accounts" ADD CONSTRAINT "positive_balance" CHECK ("balance" >= 0) NOT VALID; ALTER TABLE accounts VALIDATE CONSTRAINT positive_balance; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ConstraintMissingNotValid]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::ConstraintMissingNotValid); assert_eq!(errors.len(), 0); } @@ -254,9 +237,7 @@ CREATE TABLE "core_foo" ( ALTER TABLE "core_foo" ADD CONSTRAINT "age_restriction" CHECK ("age" >= 25); COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ConstraintMissingNotValid]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::ConstraintMissingNotValid); assert_eq!(errors.len(), 0); } @@ -269,10 +250,7 @@ CREATE TABLE "core_foo" ( ); ALTER TABLE "core_foo" ADD CONSTRAINT "age_restriction" CHECK ("age" >= 25); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ConstraintMissingNotValid]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::ConstraintMissingNotValid); assert_eq!(errors.len(), 0); } @@ -285,10 +263,7 @@ CREATE TABLE "core_foo" ( ); ALTER TABLE "core_foo" ADD CONSTRAINT "age_restriction" CHECK ("age" >= 25); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ConstraintMissingNotValid]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::ConstraintMissingNotValid); assert_eq!(errors.len(), 0); } @@ -297,9 +272,7 @@ ALTER TABLE "core_foo" ADD CONSTRAINT "age_restriction" CHECK ("age" >= 25); let sql = r#" ALTER TABLE "app_email" ADD CONSTRAINT "email_uniq" UNIQUE USING INDEX "email_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::ConstraintMissingNotValid]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::ConstraintMissingNotValid); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/disallow_unique_constraint.rs b/crates/squawk_linter/src/rules/disallow_unique_constraint.rs index 0b9a7245..56cf0970 100644 --- a/crates/squawk_linter/src/rules/disallow_unique_constraint.rs +++ b/crates/squawk_linter/src/rules/disallow_unique_constraint.rs @@ -65,16 +65,14 @@ pub(crate) fn disallow_unique_constraint(ctx: &mut Linter, parse: &Parse mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { @@ -61,9 +62,7 @@ create table users ( id serial4 ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferBigintOverInt]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferBigintOverInt); assert_ne!(errors.len(), 0); assert_eq!(errors.len(), 4); assert_eq!( @@ -104,9 +103,7 @@ create table users ( id serial2 ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferBigintOverInt]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferBigintOverInt); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/prefer_bigint_over_smallint.rs b/crates/squawk_linter/src/rules/prefer_bigint_over_smallint.rs index 530f8247..91c8a626 100644 --- a/crates/squawk_linter/src/rules/prefer_bigint_over_smallint.rs +++ b/crates/squawk_linter/src/rules/prefer_bigint_over_smallint.rs @@ -42,7 +42,8 @@ pub(crate) fn prefer_bigint_over_smallint(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { @@ -71,9 +72,7 @@ create table users ( id BIGSERIAL ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferIdentity]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferIdentity); assert_ne!(errors.len(), 0); assert_eq!(errors.len(), 7); assert_eq!( @@ -96,9 +95,7 @@ create table users ( id "bigserial" ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferIdentity]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferIdentity); assert_eq!(errors.len(), 2); assert_debug_snapshot!(errors); } @@ -113,9 +110,7 @@ create table users ( id bigint generated always as identity primary key ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferIdentity]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferIdentity); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/prefer_robust_stmts.rs b/crates/squawk_linter/src/rules/prefer_robust_stmts.rs index dccc8ac5..a2bf6f79 100644 --- a/crates/squawk_linter/src/rules/prefer_robust_stmts.rs +++ b/crates/squawk_linter/src/rules/prefer_robust_stmts.rs @@ -251,14 +251,15 @@ pub(crate) fn prefer_robust_stmts(ctx: &mut Linter, parse: &Parse) { mod test { use insta::{assert_debug_snapshot, assert_snapshot}; - use crate::{Edit, Linter, Rule}; + use crate::{Edit, Linter, Rule, test_utils::{lint, lint_with_assume_in_transaction}}; fn fix(sql: &str) -> String { let file = squawk_syntax::SourceFile::parse(sql); + assert_eq!(file.errors().len(), 0); assert_eq!(file.errors().len(), 0, "Shouldn't start with syntax errors"); let mut linter = Linter::from([Rule::PreferRobustStmts]); let errors = linter.lint(file, sql); - assert!(errors.len() > 0, "Should start with linter errors"); + assert!(!errors.is_empty(), "Should start with linter errors"); let fixes = errors.into_iter().flat_map(|x| x.fix).collect::>(); @@ -386,9 +387,7 @@ ALTER TABLE users DROP CONSTRAINT pk_users; ALTER TABLE "app_email" DROP CONSTRAINT IF EXISTS "email_uniq"; ALTER TABLE "app_email" ADD CONSTRAINT "email_uniq" UNIQUE USING INDEX "email_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -398,9 +397,7 @@ ALTER TABLE "app_email" ADD CONSTRAINT "email_uniq" UNIQUE USING INDEX "email_id select 1; -- so we don't skip checking DROP INDEX CONCURRENTLY IF EXISTS "email_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -411,9 +408,7 @@ ALTER TABLE "app_email" DROP CONSTRAINT IF EXISTS "fk_user"; ALTER TABLE "app_email" ADD CONSTRAINT "fk_user" FOREIGN KEY ("user_id") REFERENCES "app_user" ("id") DEFERRABLE INITIALLY DEFERRED NOT VALID; ALTER TABLE "app_email" VALIDATE CONSTRAINT "fk_user"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -424,9 +419,7 @@ BEGIN; ALTER TABLE "core_foo" ADD COLUMN "answer_id" integer NULL; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -436,9 +429,7 @@ COMMIT; select 1; -- so we don't skip checking ALTER TABLE "core_foo" ADD COLUMN IF NOT EXISTS "answer_id" integer NULL; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -448,9 +439,7 @@ ALTER TABLE "core_foo" ADD COLUMN IF NOT EXISTS "answer_id" integer NULL; select 1; -- so we don't skip checking CREATE INDEX CONCURRENTLY IF NOT EXISTS "core_foo_idx" ON "core_foo" ("answer_id"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -464,9 +453,7 @@ CREATE TABLE "core_bar" ( ); COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -478,9 +465,7 @@ CREATE TABLE IF NOT EXISTS "core_bar" ( "bravo" text NOT NULL ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -494,9 +479,7 @@ DROP TABLE "core_bar"; DROP TYPE foo; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -507,9 +490,7 @@ COMMIT; select 1; -- so we don't skip checking SELECT 1; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -520,9 +501,7 @@ SELECT 1; select 1; -- so we don't skip checking INSERT INTO tbl VALUES (a); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -533,9 +512,7 @@ INSERT INTO tbl VALUES (a); select 1; -- so we don't skip checking ALTER TABLE "core_foo" DROP CONSTRAINT IF EXISTS "core_foo_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -545,10 +522,7 @@ ALTER TABLE "core_foo" DROP CONSTRAINT IF EXISTS "core_foo_idx"; select 1; -- so we don't skip checking ALTER TABLE "core_foo" ADD COLUMN "answer_id" integer NULL; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -559,10 +533,7 @@ DROP INDEX "core_bar_foo_id_idx"; DROP TABLE "core_bar"; DROP TYPE foo; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -574,10 +545,7 @@ CREATE TABLE "core_bar" ( "bravo" text NOT NULL ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -588,10 +556,7 @@ CREATE TABLE "core_bar" ( let sql = r#" CREATE INDEX CONCURRENTLY ON "table_name" ("field_name"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -601,10 +566,7 @@ CREATE INDEX CONCURRENTLY ON "table_name" ("field_name"); CREATE INDEX CONCURRENTLY ON "table_name" ("field_name"); CREATE INDEX CONCURRENTLY ON "table_name" ("field_name"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -623,10 +585,7 @@ ALTER TABLE "D" DROP CONSTRAINT "UQ_468cad3743146a81c94b0b114ac"; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -636,9 +595,7 @@ COMMIT; select 1; -- so we don't skip checking ALTER TABLE "core_foo" ADD COLUMN "answer_id" integer NULL; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -649,9 +606,7 @@ ALTER TABLE "core_foo" ADD COLUMN "answer_id" integer NULL; select 1; -- so we don't skip checking CREATE INDEX CONCURRENTLY "core_foo_idx" ON "core_foo" ("answer_id"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -662,9 +617,7 @@ CREATE INDEX CONCURRENTLY "core_foo_idx" ON "core_foo" ("answer_id"); select 1; -- so we don't skip checking alter table t drop column c cascade; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -675,9 +628,7 @@ alter table t drop column c cascade; select 1; -- so we don't skip checking alter table t drop column if exists c cascade; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -687,9 +638,7 @@ alter table t drop column if exists c cascade; select 1; -- so we don't skip checking CREATE TABLE "core_bar" ( "id" serial NOT NULL PRIMARY KEY, "bravo" text NOT NULL); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -700,9 +649,7 @@ CREATE TABLE "core_bar" ( "id" serial NOT NULL PRIMARY KEY, "bravo" text NOT NUL select 1; -- so we don't skip checking ALTER TABLE "core_foo" DROP CONSTRAINT "core_foo_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -713,9 +660,7 @@ ALTER TABLE "core_foo" DROP CONSTRAINT "core_foo_idx"; select 1; -- so we don't skip checking CREATE INDEX CONCURRENTLY ON "table_name" ("field_name"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_eq!(errors.len(), 0); } @@ -725,9 +670,7 @@ CREATE INDEX CONCURRENTLY ON "table_name" ("field_name"); CREATE TABLE IF NOT EXISTS test(); ALTER TABLE IF EXISTS test ENABLE ROW LEVEL SECURITY; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -738,9 +681,7 @@ ALTER TABLE IF EXISTS test ENABLE ROW LEVEL SECURITY; CREATE TABLE IF NOT EXISTS test(); ALTER TABLE test ENABLE ROW LEVEL SECURITY; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -751,9 +692,7 @@ ALTER TABLE test ENABLE ROW LEVEL SECURITY; CREATE TABLE IF NOT EXISTS test(); ALTER TABLE IF EXISTS test DISABLE ROW LEVEL SECURITY; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -764,11 +703,9 @@ ALTER TABLE IF EXISTS test DISABLE ROW LEVEL SECURITY; ALTER TABLE "app_email" DROP CONSTRAINT IF EXISTS "email_uniq"; ALTER TABLE "app_email" ADD CONSTRAINT "email_uniq" UNIQUE USING INDEX "email_idx"; -- this second add constraint should error because it's not robust -ALTER TABLE "app_email" ADD CONSTRAIN "email_uniq" UNIQUE USING INDEX "email_idx"; +ALTER TABLE "app_email" ADD CONSTRAINT "email_uniq" UNIQUE USING INDEX "email_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -779,9 +716,7 @@ ALTER TABLE "app_email" ADD CONSTRAIN "email_uniq" UNIQUE USING INDEX "email_idx select 1; -- so we don't skip checking alter table t alter column c set not null; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -792,9 +727,7 @@ alter table t alter column c set not null; select 1; -- so we don't skip checking DROP INDEX CONCURRENTLY "email_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferRobustStmts]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferRobustStmts); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/prefer_text_field.rs b/crates/squawk_linter/src/rules/prefer_text_field.rs index e4ff5375..42498b40 100644 --- a/crates/squawk_linter/src/rules/prefer_text_field.rs +++ b/crates/squawk_linter/src/rules/prefer_text_field.rs @@ -71,7 +71,8 @@ pub(crate) fn prefer_text_field(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; /// Changing a column of varchar(255) to varchar(1000) requires an ACCESS /// EXCLUSIVE lock @@ -85,9 +86,7 @@ BEGIN; ALTER TABLE "core_foo" ALTER COLUMN "kind" TYPE varchar(1000) USING "kind"::varchar(1000); COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTextField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTextField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -105,9 +104,7 @@ CREATE TABLE "core_bar" ( ); COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTextField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTextField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -120,9 +117,7 @@ create table t ( "alpha" pg_catalog.varchar(100) NOT NULL ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTextField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTextField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -134,9 +129,7 @@ BEGIN; ALTER TABLE "foo_table" ADD COLUMN "foo_column" varchar(256) NULL; COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTextField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTextField); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -146,9 +139,7 @@ COMMIT; let sql = r#" CREATE TABLE IF NOT EXISTS foo_table(bar_col varchar); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTextField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTextField); assert_eq!(errors.len(), 0); } @@ -169,9 +160,7 @@ CREATE TABLE "core_bar" ( ALTER TABLE "core_bar" ADD CONSTRAINT "text_size" CHECK (LENGTH("bravo") <= 100); COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTextField]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTextField); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/prefer_timestamptz.rs b/crates/squawk_linter/src/rules/prefer_timestamptz.rs index b5587db1..dcd5400c 100644 --- a/crates/squawk_linter/src/rules/prefer_timestamptz.rs +++ b/crates/squawk_linter/src/rules/prefer_timestamptz.rs @@ -66,7 +66,8 @@ pub(crate) fn prefer_timestamptz(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn create_table_with_timestamp_err() { @@ -80,9 +81,7 @@ create table app.accounts created_ts timestamp without time zone ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTimestampTz]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTimestampTz); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -95,9 +94,7 @@ alter table app.users alter table app.accounts alter column created_ts type timestamp without time zone; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTimestampTz]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTimestampTz); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -114,9 +111,7 @@ create table app.accounts created_ts timestamp with time zone ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTimestampTz]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTimestampTz); assert_eq!(errors.len(), 0); } @@ -132,9 +127,7 @@ create table app.accounts created_ts timestamp with time zone ); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::PreferTimestampTz]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::PreferTimestampTz); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/renaming_column.rs b/crates/squawk_linter/src/rules/renaming_column.rs index 879c7bb7..79779df9 100644 --- a/crates/squawk_linter/src/rules/renaming_column.rs +++ b/crates/squawk_linter/src/rules/renaming_column.rs @@ -27,16 +27,15 @@ pub(crate) fn renaming_column(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { let sql = r#" ALTER TABLE "table_name" RENAME COLUMN "column_name" TO "new_column_name"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RenamingColumn]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RenamingColumn); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/renaming_table.rs b/crates/squawk_linter/src/rules/renaming_table.rs index 955b3498..b789220d 100644 --- a/crates/squawk_linter/src/rules/renaming_table.rs +++ b/crates/squawk_linter/src/rules/renaming_table.rs @@ -27,16 +27,15 @@ pub(crate) fn renaming_table(ctx: &mut Linter, parse: &Parse) { mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn err() { let sql = r#" ALTER TABLE "table_name" RENAME TO "new_table_name"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RenamingTable]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RenamingTable); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } diff --git a/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs b/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs index c76b325e..8bfeaa59 100644 --- a/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs +++ b/crates/squawk_linter/src/rules/require_concurrent_index_creation.rs @@ -37,7 +37,7 @@ pub(crate) fn require_concurrent_index_creation(ctx: &mut Linter, parse: &Parse< mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::{Rule, test_utils::{lint, lint_with_assume_in_transaction}}; /// ```sql /// -- instead of @@ -51,9 +51,7 @@ mod test { -- instead of CREATE INDEX "field_name_idx" ON "table_name" ("field_name"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexCreation]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexCreation); assert_ne!(errors.len(), 0); assert_debug_snapshot!(errors); } @@ -64,9 +62,7 @@ CREATE INDEX "field_name_idx" ON "table_name" ("field_name"); -- use CONCURRENTLY CREATE INDEX CONCURRENTLY "field_name_idx" ON "table_name" ("field_name"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexCreation]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexCreation); assert_eq!(errors.len(), 0); } @@ -81,9 +77,7 @@ CREATE TABLE "core_foo" ( CREATE INDEX "core_foo_tenant_id_4d397ef9" ON "core_foo" ("tenant_id"); COMMIT; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexCreation]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexCreation); assert_eq!(errors.len(), 0); } @@ -96,10 +90,7 @@ CREATE TABLE "core_foo" ( ); CREATE INDEX "core_foo_tenant_id_4d397ef9" ON "core_foo" ("tenant_id"); "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexCreation]); - linter.settings.assume_in_transaction = true; - let errors = linter.lint(file, sql); + let errors = lint_with_assume_in_transaction(sql, Rule::RequireConcurrentIndexCreation); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/require_concurrent_index_deletion.rs b/crates/squawk_linter/src/rules/require_concurrent_index_deletion.rs index 899dd1dd..7074c64f 100644 --- a/crates/squawk_linter/src/rules/require_concurrent_index_deletion.rs +++ b/crates/squawk_linter/src/rules/require_concurrent_index_deletion.rs @@ -25,7 +25,8 @@ pub(crate) fn require_concurrent_index_deletion(ctx: &mut Linter, parse: &Parse< mod test { use insta::assert_debug_snapshot; - use crate::{Linter, Rule}; + use crate::Rule; + use crate::test_utils::lint; #[test] fn drop_index_missing_concurrently_err() { @@ -33,9 +34,7 @@ mod test { -- instead of DROP INDEX IF EXISTS "field_name_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexDeletion]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexDeletion); assert_eq!(errors.len(), 1); assert_eq!(errors[0].code, Rule::RequireConcurrentIndexDeletion); assert_debug_snapshot!(errors); @@ -46,9 +45,7 @@ mod test { let sql = r#" DROP INDEX CONCURRENTLY IF EXISTS "field_name_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexDeletion]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexDeletion); assert_eq!(errors.len(), 0); } @@ -57,9 +54,7 @@ DROP INDEX CONCURRENTLY IF EXISTS "field_name_idx"; let sql = r#" DROP INDEX CONCURRENTLY IF EXISTS "field_name_idx"; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexDeletion]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexDeletion); assert_eq!(errors.len(), 0); } @@ -68,9 +63,7 @@ DROP INDEX CONCURRENTLY IF EXISTS "field_name_idx"; let sql = r#" DROP TABLE IF EXISTS some_table; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexDeletion]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexDeletion); assert_eq!(errors.len(), 0); } @@ -79,9 +72,7 @@ DROP TABLE IF EXISTS some_table; let sql = r#" DROP TRIGGER IF EXISTS trigger on foo_table; "#; - let file = squawk_syntax::SourceFile::parse(sql); - let mut linter = Linter::from([Rule::RequireConcurrentIndexDeletion]); - let errors = linter.lint(file, sql); + let errors = lint(sql, Rule::RequireConcurrentIndexDeletion); assert_eq!(errors.len(), 0); } } diff --git a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__double_add_after_drop_err.snap b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__double_add_after_drop_err.snap index b07be17e..f7f0c201 100644 --- a/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__double_add_after_drop_err.snap +++ b/crates/squawk_linter/src/rules/snapshots/squawk_linter__rules__prefer_robust_stmts__test__double_add_after_drop_err.snap @@ -5,8 +5,8 @@ expression: errors [ Violation { code: PreferRobustStmts, - message: "Missing `IF NOT EXISTS`, the migration can't be rerun if it fails part way through.", - text_range: 240..297, + message: "Missing transaction, the migration can't be rerun if it fails part way through.", + text_range: 240..298, help: None, fix: None, }, diff --git a/crates/squawk_linter/src/test_utils.rs b/crates/squawk_linter/src/test_utils.rs new file mode 100644 index 00000000..e8029281 --- /dev/null +++ b/crates/squawk_linter/src/test_utils.rs @@ -0,0 +1,16 @@ +use crate::{Linter, Rule, Violation}; + +pub(crate) fn lint(sql: &str, rule: Rule) -> Vec { + let file = squawk_syntax::SourceFile::parse(sql); + assert_eq!(file.errors().len(), 0); + let mut linter = Linter::from([rule]); + linter.lint(file, sql) +} + +pub(crate) fn lint_with_assume_in_transaction(sql: &str, rule: Rule) -> Vec { + let file = squawk_syntax::SourceFile::parse(sql); + assert_eq!(file.errors().len(), 0); + let mut linter = Linter::from([rule]); + linter.settings.assume_in_transaction = true; + linter.lint(file, sql) +} diff --git a/crates/squawk_linter/src/version.rs b/crates/squawk_linter/src/version.rs index eca129b0..268b5e93 100644 --- a/crates/squawk_linter/src/version.rs +++ b/crates/squawk_linter/src/version.rs @@ -25,6 +25,12 @@ impl Version { } } +impl Default for Version { + fn default() -> Version { + Version::new(15, 0, 0) + } +} + // Allow us to deserialize our version from a string in .squawk.toml. // from https://stackoverflow.com/a/46755370/ impl<'de> Deserialize<'de> for Version {