Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2018-11-29 14:44:48 +0300
committerKamil Trzciński <ayufan@ayufan.eu>2018-11-29 18:09:18 +0300
commit64b1044e7ac22d14a9c17ef773dd075b74df00fa (patch)
tree7b3c6d04c96ceb9183c745d67c34c8b9d4c8da1b /spec/lib/gitlab/config
parent6775dafa3816239f6fa1b12428df42572be5a158 (diff)
ci/config: generalize Config validation into Gitlab::Config:: module
This decouples Ci::Config to provide a common interface for handling user configuration files.
Diffstat (limited to 'spec/lib/gitlab/config')
-rw-r--r--spec/lib/gitlab/config/entry/attributable_spec.rb60
-rw-r--r--spec/lib/gitlab/config/entry/boolean_spec.rb34
-rw-r--r--spec/lib/gitlab/config/entry/configurable_spec.rb53
-rw-r--r--spec/lib/gitlab/config/entry/factory_spec.rb95
-rw-r--r--spec/lib/gitlab/config/entry/simplifiable_spec.rb88
-rw-r--r--spec/lib/gitlab/config/entry/undefined_spec.rb41
-rw-r--r--spec/lib/gitlab/config/entry/unspecified_spec.rb32
-rw-r--r--spec/lib/gitlab/config/entry/validatable_spec.rb54
-rw-r--r--spec/lib/gitlab/config/entry/validator_spec.rb55
-rw-r--r--spec/lib/gitlab/config/loader/yaml_spec.rb60
10 files changed, 572 insertions, 0 deletions
diff --git a/spec/lib/gitlab/config/entry/attributable_spec.rb b/spec/lib/gitlab/config/entry/attributable_spec.rb
new file mode 100644
index 00000000000..abb4fff3ad7
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/attributable_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Attributable do
+ let(:node) do
+ Class.new do
+ include Gitlab::Config::Entry::Attributable
+ end
+ end
+
+ let(:instance) { node.new }
+
+ before do
+ node.class_eval do
+ attributes :name, :test
+ end
+ end
+
+ context 'when config is a hash' do
+ before do
+ allow(instance)
+ .to receive(:config)
+ .and_return({ name: 'some name', test: 'some test' })
+ end
+
+ it 'returns the value of config' do
+ expect(instance.name).to eq 'some name'
+ expect(instance.test).to eq 'some test'
+ end
+
+ it 'returns no method error for unknown attributes' do
+ expect { instance.unknown }.to raise_error(NoMethodError)
+ end
+ end
+
+ context 'when config is not a hash' do
+ before do
+ allow(instance)
+ .to receive(:config)
+ .and_return('some test')
+ end
+
+ it 'returns nil' do
+ expect(instance.test).to be_nil
+ end
+ end
+
+ context 'when method is already defined in a superclass' do
+ it 'raises an error' do
+ expectation = expect do
+ Class.new(String) do
+ include Gitlab::Config::Entry::Attributable
+
+ attributes :length
+ end
+ end
+
+ expectation.to raise_error(ArgumentError, 'Method already defined!')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/boolean_spec.rb b/spec/lib/gitlab/config/entry/boolean_spec.rb
new file mode 100644
index 00000000000..1b7a3f850ec
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/boolean_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Boolean do
+ let(:entry) { described_class.new(config) }
+
+ describe 'validations' do
+ context 'when entry config value is valid' do
+ let(:config) { false }
+
+ describe '#value' do
+ it 'returns key value' do
+ expect(entry.value).to eq false
+ end
+ end
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when entry value is not valid' do
+ let(:config) { ['incorrect'] }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors)
+ .to include 'boolean config should be a boolean value'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/configurable_spec.rb b/spec/lib/gitlab/config/entry/configurable_spec.rb
new file mode 100644
index 00000000000..85a7cf1d241
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/configurable_spec.rb
@@ -0,0 +1,53 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Configurable do
+ let(:entry) do
+ Class.new(Gitlab::Config::Entry::Node) do
+ include Gitlab::Config::Entry::Configurable
+ end
+ end
+
+ describe 'validations' do
+ context 'when entry is a hash' do
+ let(:instance) { entry.new(key: 'value') }
+
+ it 'correctly validates an instance' do
+ expect(instance).to be_valid
+ end
+ end
+
+ context 'when entry is not a hash' do
+ let(:instance) { entry.new('ls') }
+
+ it 'invalidates the instance' do
+ expect(instance).not_to be_valid
+ end
+ end
+ end
+
+ describe 'configured entries' do
+ before do
+ entry.class_eval do
+ entry :object, Object, description: 'test object'
+ end
+ end
+
+ describe '.nodes' do
+ it 'has valid nodes' do
+ expect(entry.nodes).to include :object
+ end
+
+ it 'creates a node factory' do
+ expect(entry.nodes[:object])
+ .to be_an_instance_of Gitlab::Config::Entry::Factory
+ end
+
+ it 'returns a duplicated factory object' do
+ first_factory = entry.nodes[:object]
+ second_factory = entry.nodes[:object]
+
+ expect(first_factory).not_to be_equal(second_factory)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/factory_spec.rb b/spec/lib/gitlab/config/entry/factory_spec.rb
new file mode 100644
index 00000000000..c29d17eaee3
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/factory_spec.rb
@@ -0,0 +1,95 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Factory do
+ describe '#create!' do
+ class Script < Gitlab::Config::Entry::Node
+ include Gitlab::Config::Entry::Validatable
+
+ validations do
+ validates :config, array_of_strings: true
+ end
+ end
+
+ let(:entry) { Script }
+ let(:factory) { described_class.new(entry) }
+
+ context 'when setting a concrete value' do
+ it 'creates entry with valid value' do
+ entry = factory
+ .value(%w(ls pwd))
+ .create!
+
+ expect(entry.value).to eq %w(ls pwd)
+ end
+
+ context 'when setting description' do
+ it 'creates entry with description' do
+ entry = factory
+ .value(%w(ls pwd))
+ .with(description: 'test description')
+ .create!
+
+ expect(entry.value).to eq %w(ls pwd)
+ expect(entry.description).to eq 'test description'
+ end
+ end
+
+ context 'when setting key' do
+ it 'creates entry with custom key' do
+ entry = factory
+ .value(%w(ls pwd))
+ .with(key: 'test key')
+ .create!
+
+ expect(entry.key).to eq 'test key'
+ end
+ end
+
+ context 'when setting a parent' do
+ let(:object) { Object.new }
+
+ it 'creates entry with valid parent' do
+ entry = factory
+ .value('ls')
+ .with(parent: object)
+ .create!
+
+ expect(entry.parent).to eq object
+ end
+ end
+ end
+
+ context 'when not setting a value' do
+ it 'raises error' do
+ expect { factory.create! }.to raise_error(
+ Gitlab::Config::Entry::Factory::InvalidFactory
+ )
+ end
+ end
+
+ context 'when creating entry with nil value' do
+ it 'creates an unspecified entry' do
+ entry = factory
+ .value(nil)
+ .create!
+
+ expect(entry)
+ .not_to be_specified
+ end
+ end
+
+ context 'when passing metadata' do
+ let(:entry) { spy('entry') }
+
+ it 'passes metadata as a parameter' do
+ factory
+ .value('some value')
+ .metadata(some: 'hash')
+ .create!
+
+ expect(entry).to have_received(:new)
+ .with('some value', { some: 'hash' })
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/simplifiable_spec.rb b/spec/lib/gitlab/config/entry/simplifiable_spec.rb
new file mode 100644
index 00000000000..bc8387ada67
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/simplifiable_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Simplifiable do
+ describe '.strategy' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> { 'condition' }
+ strategy :DifferentOne, if: -> { 'condition' }
+ end
+ end
+
+ it 'defines entry strategies' do
+ expect(entry.strategies.size).to eq 2
+ expect(entry.strategies.map(&:name))
+ .to eq %i[Something DifferentOne]
+ end
+ end
+
+ describe 'setting strategy by a condition' do
+ let(:first) { double('first strategy') }
+ let(:second) { double('second strategy') }
+ let(:unknown) { double('unknown strategy') }
+
+ before do
+ stub_const("#{described_class.name}::Something", first)
+ stub_const("#{described_class.name}::DifferentOne", second)
+ stub_const("#{described_class.name}::UnknownStrategy", unknown)
+ end
+
+ context 'when first strategy should be used' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (arg) { arg == 'something' }
+ strategy :DifferentOne, if: -> (*) { false }
+ end
+ end
+
+ it 'attemps to load a first strategy' do
+ expect(first).to receive(:new).with('something', anything)
+
+ entry.new('something')
+ end
+ end
+
+ context 'when second strategy should be used' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (arg) { arg == 'something' }
+ strategy :DifferentOne, if: -> (arg) { arg == 'test' }
+ end
+ end
+
+ it 'attemps to load a second strategy' do
+ expect(second).to receive(:new).with('test', anything)
+
+ entry.new('test')
+ end
+ end
+
+ context 'when neither one is a valid strategy' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (*) { false }
+ strategy :DifferentOne, if: -> (*) { false }
+ end
+ end
+
+ it 'instantiates an unknown strategy' do
+ expect(unknown).to receive(:new).with('test', anything)
+
+ entry.new('test')
+ end
+ end
+ end
+
+ context 'when a unknown strategy class is not defined' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :String, if: -> (*) { true }
+ end
+ end
+
+ it 'raises an error when being initialized' do
+ expect { entry.new('something') }
+ .to raise_error ArgumentError, /UndefinedStrategy not available!/
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/undefined_spec.rb b/spec/lib/gitlab/config/entry/undefined_spec.rb
new file mode 100644
index 00000000000..48f9d276c95
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/undefined_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Undefined do
+ let(:entry) { described_class.new }
+
+ describe '#leaf?' do
+ it 'is leaf node' do
+ expect(entry).to be_leaf
+ end
+ end
+
+ describe '#valid?' do
+ it 'is always valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ describe '#errors' do
+ it 'is does not contain errors' do
+ expect(entry.errors).to be_empty
+ end
+ end
+
+ describe '#value' do
+ it 'returns nil' do
+ expect(entry.value).to eq nil
+ end
+ end
+
+ describe '#relevant?' do
+ it 'is not relevant' do
+ expect(entry.relevant?).to eq false
+ end
+ end
+
+ describe '#specified?' do
+ it 'is not defined' do
+ expect(entry.specified?).to eq false
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/unspecified_spec.rb b/spec/lib/gitlab/config/entry/unspecified_spec.rb
new file mode 100644
index 00000000000..64421824a12
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/unspecified_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Unspecified do
+ let(:unspecified) { described_class.new(entry) }
+ let(:entry) { spy('Entry') }
+
+ describe '#valid?' do
+ it 'delegates method to entry' do
+ expect(unspecified.valid?).to eq entry
+ end
+ end
+
+ describe '#errors' do
+ it 'delegates method to entry' do
+ expect(unspecified.errors).to eq entry
+ end
+ end
+
+ describe '#value' do
+ it 'delegates method to entry' do
+ expect(unspecified.value).to eq entry
+ end
+ end
+
+ describe '#specified?' do
+ it 'is always false' do
+ allow(entry).to receive(:specified?).and_return(true)
+
+ expect(unspecified.specified?).to be false
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/validatable_spec.rb b/spec/lib/gitlab/config/entry/validatable_spec.rb
new file mode 100644
index 00000000000..5a8f9766d23
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/validatable_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Validatable do
+ let(:entry) do
+ Class.new(Gitlab::Config::Entry::Node) do
+ include Gitlab::Config::Entry::Validatable
+ end
+ end
+
+ describe '.validator' do
+ before do
+ entry.class_eval do
+ attr_accessor :test_attribute
+
+ validations do
+ validates :test_attribute, presence: true
+ end
+ end
+ end
+
+ it 'returns validator' do
+ expect(entry.validator.superclass)
+ .to be Gitlab::Config::Entry::Validator
+ end
+
+ it 'returns only one validator to mitigate leaks' do
+ expect { entry.validator }.not_to change { entry.validator }
+ end
+
+ context 'when validating entry instance' do
+ let(:entry_instance) { entry.new('something') }
+
+ context 'when attribute is valid' do
+ before do
+ entry_instance.test_attribute = 'valid'
+ end
+
+ it 'instance of validator is valid' do
+ expect(entry.validator.new(entry_instance)).to be_valid
+ end
+ end
+
+ context 'when attribute is not valid' do
+ before do
+ entry_instance.test_attribute = nil
+ end
+
+ it 'instance of validator is invalid' do
+ expect(entry.validator.new(entry_instance)).to be_invalid
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/validator_spec.rb b/spec/lib/gitlab/config/entry/validator_spec.rb
new file mode 100644
index 00000000000..efa16c4265c
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/validator_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Validator do
+ let(:validator) { Class.new(described_class) }
+ let(:validator_instance) { validator.new(node) }
+ let(:node) { spy('node') }
+
+ before do
+ allow(node).to receive(:key).and_return('node')
+ allow(node).to receive(:ancestors).and_return([])
+ end
+
+ describe 'delegated validator' do
+ before do
+ validator.class_eval do
+ validates :test_attribute, presence: true
+ end
+ end
+
+ context 'when node is valid' do
+ before do
+ allow(node).to receive(:test_attribute).and_return('valid value')
+ end
+
+ it 'validates attribute in node' do
+ expect(node).to receive(:test_attribute)
+ expect(validator_instance).to be_valid
+ end
+
+ it 'returns no errors' do
+ validator_instance.validate
+
+ expect(validator_instance.messages).to be_empty
+ end
+ end
+
+ context 'when node is invalid' do
+ before do
+ allow(node).to receive(:test_attribute).and_return(nil)
+ end
+
+ it 'validates attribute in node' do
+ expect(node).to receive(:test_attribute)
+ expect(validator_instance).to be_invalid
+ end
+
+ it 'returns errors' do
+ validator_instance.validate
+
+ expect(validator_instance.messages)
+ .to include /test attribute can't be blank/
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/loader/yaml_spec.rb b/spec/lib/gitlab/config/loader/yaml_spec.rb
new file mode 100644
index 00000000000..44c9a3896a8
--- /dev/null
+++ b/spec/lib/gitlab/config/loader/yaml_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Loader::Yaml do
+ let(:loader) { described_class.new(yml) }
+
+ context 'when yaml syntax is correct' do
+ let(:yml) { 'image: ruby:2.2' }
+
+ describe '#valid?' do
+ it 'returns true' do
+ expect(loader.valid?).to be true
+ end
+ end
+
+ describe '#load!' do
+ it 'returns a valid hash' do
+ expect(loader.load!).to eq(image: 'ruby:2.2')
+ end
+ end
+ end
+
+ context 'when yaml syntax is incorrect' do
+ let(:yml) { '// incorrect' }
+
+ describe '#valid?' do
+ it 'returns false' do
+ expect(loader.valid?).to be false
+ end
+ end
+
+ describe '#load!' do
+ it 'raises error' do
+ expect { loader.load! }.to raise_error(
+ Gitlab::Config::Loader::FormatError,
+ 'Invalid configuration format'
+ )
+ end
+ end
+ end
+
+ context 'when there is an unknown alias' do
+ let(:yml) { 'steps: *bad_alias' }
+
+ describe '#initialize' do
+ it 'raises FormatError' do
+ expect { loader }.to raise_error(Gitlab::Config::Loader::FormatError, 'Unknown alias: bad_alias')
+ end
+ end
+ end
+
+ context 'when yaml config is empty' do
+ let(:yml) { '' }
+
+ describe '#valid?' do
+ it 'returns false' do
+ expect(loader.valid?).to be false
+ end
+ end
+ end
+end