# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'spec_helper'

describe SOA, "when new" do

  before(:each) do
    @soa = SOA.new
  end

  it "should be invalid by default" do
    @soa.should_not be_valid
  end

  it "should be unique per domain" do
    @soa.domain = Factory(:domain)
    @soa.should have(1).error_on(:domain_id)
  end

  it "should require a primary NS" do
    @soa.should have(1).error_on(:primary_ns)
  end

  it "should require a contact" do
    @soa.should have(1).error_on(:contact)
  end

  it "should require a valid email address for the contact" do
    @soa.contact = 'test'
    @soa.should have(1).error_on(:contact)

    @soa.contact = 'test@example'
    @soa.should have(1).error_on(:contact)

    @soa.contact = 'test@example.com'
    @soa.should have(:no).errors_on(:contact)
  end

  it "should flip the first period in the contact to an @" do
    @soa.contact = 'test.example.com'
    @soa.contact.should == 'test@example.com'

    @soa.contact = 'test@example.com'
    @soa.contact.should == 'test@example.com'
  end

  it "should have an autogenerated serial" do
    @soa.serial.should_not be_nil
  end

  it "should only accept positive integers as serials" do
    @soa.serial = -2008040101
    @soa.should have(1).error_on(:serial)

    @soa.serial = 'ISBN123456789'
    @soa.should have(1).error_on(:serial)

    @soa.serial = 2008040101
    @soa.should have(:no).errors_on(:serial)
  end

  it "should require a refresh time" do
    @soa.should have(1).error_on(:refresh)
  end

  it "should only accept positive integers as refresh time" do
    @soa.refresh = -86400
    @soa.should have(1).error_on(:refresh)

    @soa.refresh = '12h'
    @soa.should have(1).error_on(:refresh)

    @soa.refresh = 2008040101
    @soa.should have(:no).errors_on(:refresh)
  end

  it "should require a retry time" do
    @soa.should have(1).error_on(:retry)
  end

  it "should only accept positive integers as retry time" do
    @soa.retry = -86400
    @soa.should have(1).error_on(:retry)

    @soa.retry = '15m'
    @soa.should have(1).error_on(:retry)

    @soa.retry = 2008040101
    @soa.should have(:no).errors_on(:retry)
  end

  it "should require a expiry time" do
    @soa.should have(1).error_on(:expire)
  end

  it "should only accept positive integers as expiry times" do
    @soa.expire = -86400
    @soa.should have(1).error_on(:expire)

    @soa.expire = '2w'
    @soa.should have(1).error_on(:expire)

    @soa.expire = 2008040101
    @soa.should have(:no).errors_on(:expire)
  end

  it "should require a minimum time" do
    @soa.should have(1).error_on(:minimum)
  end

  it "should only accept positive integers as minimum times" do
    @soa.minimum = -86400
    @soa.should have(1).error_on(:minimum)

    @soa.minimum = '3h'
    @soa.should have(1).error_on(:minimum)

    @soa.minimum = 10800
    @soa.should have(:no).errors_on(:minimum)
  end

  it "should not allow a minimum of more than 10800 seconds (RFC2308)" do
    @soa.minimum = 84600
    @soa.should have(1).error_on(:minimum)
  end

end

describe SOA, "when created" do
  before(:each) do
    @domain = Factory(:domain)
    @domain.soa_record.destroy

    @soa = SOA.new(
      :domain => @domain,
      :primary_ns => 'ns1.example.com',
      :contact => 'dnsadmin@example.com',
      :refresh => 7200,
      :retry => 1800,
      :expire => 604800,
      :minimum => 10800
    )
  end

  it "should have the convenience fields populated before save" do
    @soa.primary_ns.should eql('ns1.example.com')
  end

  it "should create a content field from the convenience fields" do
    @soa.save.should be_true

    @soa.content.should match(/ns1\.example\.com dnsadmin@example.com \d+ 7200 1800 604800 10800/)
  end

end

describe SOA, "and serial numbers" do
  before(:each) do
    @soa = Factory(:domain).soa_record
  end

  it "should have an easy way to update (without saving)" do
    serial = @soa.serial
    serial.should_not be_nil

    @soa.update_serial

    @soa.serial.should_not be( serial )
    @soa.serial.should >( serial )

    @soa.reload
    @soa.serial.should eql( serial )
  end

  it "should have an easy way to update (with saving)" do
    serial = @soa.serial
    serial.should_not be_nil

    @soa.update_serial!

    @soa.serial.should_not be( serial )
    @soa.serial.should >( serial )

    @soa.reload
    @soa.serial.should_not be( serial )
  end

  it "should update in sequence for the same day" do
    date_segment = Time.now.strftime( "%Y%m%d" )

    @soa.serial.to_s.should eql( date_segment + '00' )

    10.times { @soa.update_serial! }

    @soa.serial.to_s.should eql( date_segment + '10' )
  end
end

describe SOA, "when serializing to XML" do
  before(:each) do
    @soa = Factory(:domain).soa_record
  end

  it "should make an soa tag" do
    @soa.to_xml.should match(/<soa>/)
  end

  it "should have the custom soa attributes present" do
    xml = @soa.to_xml

    xml.should match(/<primary\-ns/)
    xml.should match(/<contact/)
    xml.should match(/<serial/)
    xml.should match(/<minimum/)
    xml.should match(/<expire/)
    xml.should match(/<refresh/)
    xml.should match(/<retry/)
  end

  it "should preserve original #to_xml options" do
    xml = @soa.to_xml :skip_instruct => true
    xml.should_not match(/<\?xml/)
  end
end
