Skip to content

Commit 0ca8b6c

Browse files
authored
Merge pull request #65 from github/kpaulisse-filter-validation
Filter validation
2 parents 7cac8af + b968f48 commit 0ca8b6c

4 files changed

Lines changed: 58 additions & 4 deletions

File tree

lib/octocatalog-diff/catalog-diff/filter.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@ module CatalogDiff
1010
class Filter
1111
attr_accessor :logger
1212

13+
# List the available filters here (by class name) for use in the validator method.
14+
AVAILABLE_FILTERS = %w(AbsentFile CompilationDir YAML).freeze
15+
16+
# Public: Determine whether a particular filter exists. This can be used to validate
17+
# a user-submitted filter.
18+
# @param filter_name [String] Proposed filter name
19+
# @return [Boolean] True if filter is valid; false otherwise
20+
def self.filter?(filter_name)
21+
AVAILABLE_FILTERS.include?(filter_name)
22+
end
23+
24+
# Public: Assert that a filter exists, and raise an error if it does not.
25+
# @param filter_name [String] Proposed filter name
26+
def self.assert_that_filter_exists(filter_name)
27+
return if filter?(filter_name)
28+
raise ArgumentError, "The filter #{filter_name} is not valid"
29+
end
30+
1331
# Public: Apply multiple filters by repeatedly calling the `filter` method for each
1432
# filter in an array. This method returns nothing.
1533
#
@@ -29,6 +47,7 @@ def self.apply_filters(result, filter_names, options = {})
2947
# @param filter_class_name [String] Filter class name (from `filter` subdirectory)
3048
# @param options [Hash] Additional options (optional) to pass to filtered? method
3149
def self.filter(result, filter_class_name, options = {})
50+
assert_that_filter_exists(filter_class_name)
3251
filter_class_name = [name.to_s, filter_class_name].join('::')
3352
obj = Kernel.const_get(filter_class_name).new(result, options[:logger])
3453
result.reject! { |item| obj.filtered?(item, options) }

lib/octocatalog-diff/cli/options/filters.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ def parse(parser, options)
1212
parser.on('--filters FILTER1[,FILTER2[,...]]', Array, 'Filters to apply') do |x|
1313
options[:filters] ||= []
1414
options[:filters].concat x
15+
16+
require_relative '../../catalog-diff/filter'
17+
options[:filters].each { |filter| OctocatalogDiff::CatalogDiff::Filter.assert_that_filter_exists(filter) }
1518
end
1619
end
1720
end

spec/octocatalog-diff/tests/catalog-diff/filter_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,35 @@ class OctocatalogDiff::CatalogDiff::Filter::Fake2 < OctocatalogDiff::CatalogDiff
1919
allow(Kernel).to receive(:const_get).with('OctocatalogDiff::CatalogDiff::Filter::Fake2').and_return(@class_2)
2020
end
2121

22+
describe '#filter?' do
23+
it 'should return false for non-existent filter' do
24+
expect(described_class.filter?('BlahBlahBlah')).to eq(false)
25+
end
26+
27+
it 'should return true for valid filter' do
28+
expect(described_class.filter?('AbsentFile')).to eq(true)
29+
end
30+
end
31+
32+
describe '#assert_that_filter_exists' do
33+
it 'should raise error for non-existent filter' do
34+
expect do
35+
described_class.assert_that_filter_exists('BlahBlahBlah')
36+
end.to raise_error(ArgumentError, 'The filter BlahBlahBlah is not valid')
37+
end
38+
39+
it 'should not raise error for valid filter' do
40+
expect { described_class.assert_that_filter_exists('AbsentFile') }.not_to raise_error
41+
end
42+
end
43+
2244
describe '#apply_filters' do
2345
it 'should call self.filter() with appropriate options for each class' do
2446
result = [false]
2547
options = { foo: 'bar' }
2648
classes = %w(Fake1 Fake2)
49+
allow(described_class).to receive(:"filter?").with('Fake1').and_return(true)
50+
allow(described_class).to receive(:"filter?").with('Fake2').and_return(true)
2751
expect_any_instance_of(@class_1).to receive(:'filtered?').with(false, foo: 'bar').and_return(false)
2852
expect_any_instance_of(@class_2).to receive(:'filtered?').with(false, foo: 'bar').and_return(false)
2953
expect { described_class.apply_filters(result, classes, options) }.not_to raise_error
@@ -34,6 +58,8 @@ class OctocatalogDiff::CatalogDiff::Filter::Fake2 < OctocatalogDiff::CatalogDiff
3458
describe '#filter' do
3559
it 'should call .filtered?() in a class and remove matching items' do
3660
result = [false, true]
61+
allow(described_class).to receive(:"filter?").with('Fake1').and_return(true)
62+
allow(described_class).to receive(:"filter?").with('Fake2').and_return(true)
3763
expect_any_instance_of(@class_1).to receive(:'filtered?').with(false, {}).and_return(false)
3864
expect_any_instance_of(@class_1).to receive(:'filtered?').with(true, {}).and_return(true)
3965
expect { described_class.filter(result, 'Fake1') }.not_to raise_error

spec/octocatalog-diff/tests/cli/options/filters_spec.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@
55
describe OctocatalogDiff::Cli::Options do
66
describe '#opt_ignore_equivalent_yaml_files' do
77
it 'should accept comma delimited parameters for --filters' do
8-
result = run_optparse(['--filters', 'fizzbuzz,barbuzz'])
9-
expect(result[:filters]).to eq(%w(fizzbuzz barbuzz))
8+
result = run_optparse(['--filters', 'AbsentFile,YAML'])
9+
expect(result[:filters]).to eq(%w(AbsentFile YAML))
1010
end
1111

1212
it 'should accept multiple parameters for --filters' do
13-
result = run_optparse(['--filters', 'fizzbuzz', '--filters', 'barbuzz'])
14-
expect(result[:filters]).to eq(%w(fizzbuzz barbuzz))
13+
result = run_optparse(['--filters', 'AbsentFile', '--filters', 'YAML'])
14+
expect(result[:filters]).to eq(%w(AbsentFile YAML))
15+
end
16+
17+
it 'should raise ArgumentError if invalid filter is specified' do
18+
expect do
19+
run_optparse(['--filters', 'AbsentFile,FizzBuzzDoesNotExist,YAML'])
20+
end.to raise_error(ArgumentError, 'The filter FizzBuzzDoesNotExist is not valid')
1521
end
1622
end
1723
end

0 commit comments

Comments
 (0)