debian-mirror-gitlab/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb
2020-10-24 23:57:45 +05:30

135 lines
4.4 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Expression::Parser do
before do
stub_feature_flags(ci_if_parenthesis_enabled: true)
end
describe '#tree' do
context 'validates simple operators' do
using RSpec::Parameterized::TableSyntax
where(:expression, :result_tree) do
'$VAR1 == "123"' | 'equals($VAR1, "123")'
'$VAR1 == "123" == $VAR2' | 'equals(equals($VAR1, "123"), $VAR2)'
'$VAR' | '$VAR'
'"some value"' | '"some value"'
'null' | 'null'
'$VAR1 || $VAR2 && $VAR3' | 'or($VAR1, and($VAR2, $VAR3))'
'$VAR1 && $VAR2 || $VAR3' | 'or(and($VAR1, $VAR2), $VAR3)'
'$VAR1 && $VAR2 || $VAR3 && $VAR4' | 'or(and($VAR1, $VAR2), and($VAR3, $VAR4))'
'$VAR1 && ($VAR2 || $VAR3) && $VAR4' | 'and(and($VAR1, or($VAR2, $VAR3)), $VAR4)'
end
with_them do
it { expect(described_class.seed(expression).tree.inspect).to eq(result_tree) }
end
end
context 'when combining && and OR operators' do
subject { described_class.seed('$VAR1 == "a" || $VAR2 == "b" && $VAR3 == "c" || $VAR4 == "d" && $VAR5 == "e"').tree }
context 'when parenthesis engine is enabled' do
before do
stub_feature_flags(ci_if_parenthesis_enabled: true)
end
it 'returns operations in a correct order' do
expect(subject.inspect)
.to eq('or(or(equals($VAR1, "a"), and(equals($VAR2, "b"), equals($VAR3, "c"))), and(equals($VAR4, "d"), equals($VAR5, "e")))')
end
end
context 'when parenthesis engine is disabled (legacy)' do
before do
stub_feature_flags(ci_if_parenthesis_enabled: false)
end
it 'returns operations in a invalid order' do
expect(subject.inspect)
.to eq('or(equals($VAR1, "a"), and(equals($VAR2, "b"), or(equals($VAR3, "c"), and(equals($VAR4, "d"), equals($VAR5, "e")))))')
end
end
end
context 'when using parenthesis' do
subject { described_class.seed('(($VAR1 == "a" || $VAR2 == "b") && $VAR3 == "c" || $VAR4 == "d") && $VAR5 == "e"').tree }
before do
stub_feature_flags(ci_if_parenthesis_enabled: true)
end
it 'returns operations in a correct order' do
expect(subject.inspect)
.to eq('and(or(and(or(equals($VAR1, "a"), equals($VAR2, "b")), equals($VAR3, "c")), equals($VAR4, "d")), equals($VAR5, "e"))')
end
end
context 'when expression is empty' do
it 'raises a parsing error' do
expect { described_class.seed('').tree }
.to raise_error Gitlab::Ci::Pipeline::Expression::Parser::ParseError
end
end
context 'when two value tokens have no operator' do
it 'raises a parsing error' do
expect { described_class.seed('$VAR "text"').tree }
.to raise_error Gitlab::Ci::Pipeline::Expression::Parser::ParseError
end
end
context 'when an operator has no left side' do
it 'raises an OperatorError' do
expect { described_class.seed('== "123"').tree }
.to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
end
end
context 'when an operator has no right side' do
it 'raises an OperatorError' do
expect { described_class.seed('$VAR ==').tree }
.to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
end
end
context 'when parenthesis are unmatched' do
context 'when parenthesis engine is enabled' do
before do
stub_feature_flags(ci_if_parenthesis_enabled: true)
end
where(:expression) do
[
'$VAR == (',
'$VAR2 == ("aa"',
'$VAR2 == ("aa"))',
'$VAR2 == "aa")',
'(($VAR2 == "aa")',
'($VAR2 == "aa"))'
]
end
with_them do
it 'raises a ParseError' do
expect { described_class.seed(expression).tree }
.to raise_error Gitlab::Ci::Pipeline::Expression::Parser::ParseError
end
end
end
context 'when parenthesis engine is disabled' do
before do
stub_feature_flags(ci_if_parenthesis_enabled: false)
end
it 'raises an SyntaxError' do
expect { described_class.seed('$VAR == (').tree }
.to raise_error Gitlab::Ci::Pipeline::Expression::Lexer::SyntaxError
end
end
end
end
end