# encoding: utf-8 require 'spec_helper' describe Function::Connective::Conjunction, '#optimize' do subject { object.optimize } let(:attribute) { Attribute::Integer.new(:id) } let(:object) { described_class.new(left, right) } it_should_behave_like 'Function::Connective::Binary#optimize' context 'left and right are predicates' do let(:left) { attribute.gt(1) } let(:right) { attribute.lt(3) } it { should equal(object) } it_should_behave_like 'an optimize method' end context 'left and right are inverse predicates' do let(:left) { Function::Connective::Negation.new(attribute.gt(1)) } let(:right) { Function::Connective::Negation.new(attribute.lt(3)) } it { should_not equal(object) } it 'reverses the operands' do should eql(described_class.new(attribute.lte(1), attribute.gte(3))) end it_should_behave_like 'an optimize method' end context 'left and right are the same' do let(:left) { attribute.gt(1) } let(:right) { attribute.gt(1) } it { should eql(left) } it_should_behave_like 'an optimize method' end context 'left and right are tautologys' do let(:left) { Function::Proposition::Tautology.instance } let(:right) { Function::Proposition::Tautology.instance } it { should equal(Function::Proposition::Tautology.instance) } it_should_behave_like 'an optimize method' end context 'left and right are contradictions' do let(:left) { Function::Proposition::Contradiction.instance } let(:right) { Function::Proposition::Contradiction.instance } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'right is a tautology' do let(:left) { attribute.gt(1) } let(:right) { Function::Proposition::Tautology.instance } it { should equal(left) } it_should_behave_like 'an optimize method' end context 'left is a tautology' do let(:left) { Function::Proposition::Tautology.instance } let(:right) { attribute.lt(3) } it { should equal(right) } it_should_behave_like 'an optimize method' end context 'right is a contradiction' do let(:left) { attribute.gt(1) } let(:right) { Function::Proposition::Contradiction.instance } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is a contradiction' do let(:left) { Function::Proposition::Contradiction.instance } let(:right) { attribute.lt(3) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left and right are Equality predicates for the same attribute and different values' do let(:left) { attribute.eq(1) } let(:right) { attribute.eq(3) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left and right are Inequality predicates for the same attribute and different values' do let(:left) { attribute.ne(1) } let(:right) { attribute.ne(3) } it { should eql(attribute.exclude([ 1, 3 ])) } it_should_behave_like 'an optimize method' end context 'left is an Equality and right is an Inequality predicate for the same attribute and value' do let(:left) { attribute.eq(1) } let(:right) { attribute.ne(1) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is an Inequality and right is an Equality predicate for the same attribute and value' do let(:left) { attribute.ne(1) } let(:right) { attribute.eq(1) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is an Inclusion and right is an Exclusion predicate for the same attribute and value' do let(:left) { attribute.include([ 1, 2 ]) } let(:right) { attribute.exclude([ 1, 2 ]) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is an Exclusion and right is an Inclusion predicate for the same attribute and value' do let(:left) { attribute.exclude([ 1, 2 ]) } let(:right) { attribute.include([ 1, 2 ]) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is a GreaterThan and right is a LessThanOrEqualTo predicate for the same attribute and value' do let(:left) { attribute.gt(1) } let(:right) { attribute.lte(1) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is an LessThanOrEqualTo and right is an GreaterThan predicate for the same attribute and value' do let(:left) { attribute.lte(1) } let(:right) { attribute.gt(1) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is a GreaterThanOrEqualTo and right is a LessThan predicate for the same attribute and value' do let(:left) { attribute.gte(1) } let(:right) { attribute.lt(1) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is an LessThan and right is an GreaterThanOrEqualTo predicate for the same attribute and value' do let(:left) { attribute.lt(1) } let(:right) { attribute.gte(1) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is a Match and right is a NoMatch predicate for the same attribute and value' do let(:attribute) { Attribute::String.new(:name) } let(:left) { attribute.match(/Dan Kubb/) } let(:right) { attribute.no_match(/Dan Kubb/) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left is an NoMatch and right is an Match predicate for the same attribute and value' do let(:attribute) { Attribute::String.new(:name) } let(:left) { attribute.no_match(/Dan Kubb/) } let(:right) { attribute.match(/Dan Kubb/) } it { should equal(Function::Proposition::Contradiction.instance) } it_should_behave_like 'an optimize method' end context 'left and right are predicates for the same attribute and the same values' do let(:left) { attribute.eq(1) } let(:right) { attribute.eq(1) } it { should eql(attribute.eq(1)) } it_should_behave_like 'an optimize method' end context 'left and right are predicates for the same attribute, but left.right is an attribute' do let(:other) { Attribute::Integer.new(:other_id) } let(:left) { attribute.eq(other) } let(:right) { attribute.eq(1) } it { should equal(object) } it_should_behave_like 'an optimize method' end context 'left and right are predicates for the same attribute, but right.right is an attribute' do let(:other) { Attribute::Integer.new(:other_id) } let(:left) { attribute.eq(1) } let(:right) { attribute.eq(other) } it { should equal(object) } it_should_behave_like 'an optimize method' end end