# 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.


# This file gets loaded twice when running 'spec spec/*' and not with pleasant results,
# so ignore the second attempt to load it.
unless defined?(SpecHelpers)

  require 'rubygems'

  # For testing we use the gem requirements specified on the buildr.gemspec
  spec = Gem::Specification.load(File.expand_path('../buildr.gemspec', File.dirname(__FILE__)))
  # Dependency.version_requirements deprecated in rubygems 1.3.6
  spec.dependencies.
    select {|dep| dep.type == :runtime || (dep.type == :development && dep.name.to_s =~ /^rspec.*/) }.
    each { |dep| gem dep.name, (dep.respond_to?(:requirement) ? dep.requirement.to_s : dep.version_requirements.to_s) }

  # Make sure to load from these paths first, we don't want to load any
  # code from Gem library.
  $LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__)),
                     File.expand_path('../addon', File.dirname(__FILE__))

  # Buildr uses autoload extensively, but autoload when running specs creates
  # a problem -- we sandbox $LOADED_FEATURES, so we end up autoloading the same
  # module twice. This turns autoload into a require, which is not the right
  # thing, but will do for now.
  def autoload(symbol, path)
    require path
  end
  require 'buildr'
  # load ecj
  require 'buildr/java/ecj'
  #Make ecj appear as a compiler that doesn't apply:
  class Buildr::Compiler::Ecj
    class << self
      def applies_to?(project, task)
        false
      end
    end
  end

  # Give a chance for plugins to do a few things before requiring the sandbox.
  include SandboxHook if defined?(SandboxHook)

  require File.expand_path('sandbox', File.dirname(__FILE__))

  module SpecHelpers

    include Checks::Matchers

    [:info, :warn, :error, :puts].each do |severity|
      ::Object.class_eval do
        define_method severity do |*args|
          $messages ||= {}
          $messages[severity] ||= []
          $messages[severity].push(*args)
        end
      end
    end

    class << Buildr.application
      alias :deprecated_without_capture :deprecated
      def deprecated(message)
        verbose(true) { deprecated_without_capture message }
      end
    end

    class MessageWithSeverityMatcher
      def initialize(severity, message)
        @severity = severity
        @expect = message
      end

      def matches?(target)
        $messages = {@severity => []}
        target.call
        return Regexp === @expect ? $messages[@severity].join('\n') =~ @expect : $messages[@severity].include?(@expect.to_s)
      end

      def failure_message
        "Expected #{@severity} #{@expect.inspect}, " +
          ($messages[@severity].empty? ? "no #{@severity} issued" : "found #{$messages[@severity].inspect}")
      end

      def negative_failure_message
        "Found unexpected #{$messages[@severity].inspect}"
      end
    end

    # Test if an info message was shown.  You can use a string or regular expression.
    #
    # For example:
    #   lambda { info 'ze test' }.should show_info(/ze test/)
    def show_info(message)
      MessageWithSeverityMatcher.new :info, message
    end

    # Test if a warning was shown. You can use a string or regular expression.
    #
    # For example:
    #   lambda { warn 'ze test' }.should show_warning(/ze test/)
    def show_warning(message)
      MessageWithSeverityMatcher.new :warn, message
    end

    # Test if an error message was shown.  You can use a string or regular expression.
    #
    # For example:
    #   lambda { error 'ze test' }.should show_error(/ze test/)
    def show_error(message)
      MessageWithSeverityMatcher.new :error, message
    end

    # Test if any message was shown (puts).  You can use a string or regular expression.
    #
    # For example:
    #   lambda { puts 'ze test' }.should show(/ze test/)
    def show(message)
      MessageWithSeverityMatcher.new :puts, message
    end

    # Yields a block that should try exiting the application.
    # Accepts
    #
    # For example:
    #   test_exit(1) {  puts "Hello" ; exit(1) }.should show("Hello")
    #
    def test_exit(status = nil)
      return lambda {
        begin
          yield
          raise "Exit was not called!"
        rescue SystemExit => e
          raise "Exit status incorrect! Expected: #{status}, got #{e.status}" if status && (e.status != status)
        end
      }
    end

    class ::Rake::Task
      alias :execute_without_a_record :execute
      def execute(args)
        $executed ||= []
        $executed << name
        execute_without_a_record args
      end
    end

    class InvokeMatcher
      def initialize(*tasks)
        @expecting = tasks.map { |task| [task].flatten.map(&:to_s) }
      end

      def matches?(target)
        $executed = []
        target.call
        return false unless all_ran?
        return !@but_not.any_ran? if @but_not
        return true
      end

      def failure_message
        return @but_not.negative_failure_message if all_ran? && @but_not
        "Expected the tasks #{expected} to run, but #{remaining} did not run, or not in the order we expected them to." +
          "  Tasks that ran: #{$executed.inspect}"
      end

      def negative_failure_message
        if all_ran?
          "Expected the tasks #{expected} to not run, but they all ran."
        else
          "Expected the tasks #{expected} to not run, and all but #{remaining} ran."
        end
      end

      def but_not(*tasks)
        @but_not = InvokeMatcher.new(*tasks)
        self
      end

    protected

      def expected
        @expecting.map { |tests| tests.join('=>') }.join(', ')
      end

      def remaining
        @remaining.map { |tests| tests.join('=>') }.join(', ')
      end

      def all_ran?
        @remaining ||= $executed.inject(@expecting) do |expecting, executed|
          expecting.map { |tasks| tasks.first == executed ? tasks[1..-1] : tasks }.reject(&:empty?)
        end
        @remaining.empty?
      end

      def any_ran?
        all_ran?
        @remaining.size < @expecting.size
      end

    end

    # Tests that all the tasks ran, in the order specified. Can also be used to test that some
    # tasks and not others ran.
    #
    # Takes a list of arguments. Each argument can be a task name, matching only if that task ran.
    # Each argument can be an array of task names, matching only if all these tasks ran in that order.
    # So run_tasks('foo', 'bar') expects foo and bar to run in any order, but run_task(['foo', 'bar'])
    # expects foo to run before bar.
    #
    # You can call but_not on the matchers to specify that certain tasks must not execute.
    #
    # For example:
    #   # Either task
    #   lambda { task('compile').invoke }.should run_tasks('compile', 'resources')
    #   # In that order
    #   lambda { task('build').invoke }.should run_tasks(['compile', 'test'])
    #   # With exclusion
    #   lambda { task('build').invoke }.should run_tasks('compile').but_not('install')
    def run_tasks(*tasks)
      InvokeMatcher.new *tasks
    end

    # Tests that a task ran. Similar to run_tasks, but accepts a single task name.
    #
    # For example:
    #   lambda { task('build').invoke }.should run_task('test')
    def run_task(task)
      InvokeMatcher.new [task]
    end

    class UriPathMatcher
      def initialize(re)
        @expression = re
      end

      def matches?(uri)
        @uri = uri
        uri.path =~ @expression
      end

      def description
        "URI with path matching #{@expression} vs #{@uri}"
      end

      def failure_message_for_should
        "expected #{description}"
      end
    end

    # Matches a parsed URI's path against the given regular expression
    def uri(re)
      UriPathMatcher.new(re)
    end


    class AbsolutePathMatcher
      def initialize(path)
        @expected = File.expand_path(path.to_s)
      end

      def matches?(path)
        @provided = File.expand_path(path.to_s)
        @provided == @expected
      end

      def failure_message
        "Expected path #{@expected}, but found path #{@provided}"
      end

      def negative_failure_message
        "Expected a path other than #{@expected}"
      end
    end

    def point_to_path(path)
      AbsolutePathMatcher.new(path)
    end


    # Value covered by range. For example:
    #   (1..5).should cover(3)
    RSpec::Matchers.define :cover do |actual|
      match do |range|
        actual >= range.min && actual <= range.max
      end
    end


    def suppress_stdout
      stdout = $stdout
      $stdout = StringIO.new
      begin
        yield
      ensure
        $stdout = stdout
      end
    end

    def dryrun
      Buildr.application.options.dryrun = true
      begin
        suppress_stdout { yield }
      ensure
        Buildr.application.options.dryrun = false
      end
    end

    # We run tests with tracing off. Then things break. And we need to figure out what went wrong.
    # So just use trace() as you would use verbose() to find and squash the bug.
    def trace(value = nil)
      old_value = Buildr.application.options.trace
      Buildr.application.options.trace = value unless value.nil?
      if block_given?
        begin
          yield
        ensure
          Buildr.application.options.trace = old_value
        end
      end
      Buildr.application.options.trace
    end

    # Change the Buildr original directory, faking invocation from a different directory.
    def in_original_dir(dir)
      begin
        original_dir = Buildr.application.original_dir
        Buildr.application.instance_eval { @original_dir = File.expand_path(dir) }
        yield
      ensure
        Buildr.application.instance_eval { @original_dir = original_dir }
      end
    end


    # Buildr's define method creates a project definition but does not evaluate it
    # (that happens once the buildfile is loaded), and we include Buildr's define in
    # the test context so we can use it without prefixing with Buildr. This just patches
    # define to evaluate the project definition before returning it.
    def define(name, properties = nil, &block) #:yields:project
      Project.define(name, properties, &block).tap { |project| project.invoke }
    end

  end


  # Allow using matchers within the project definition.
  class Buildr::Project
    include ::RSpec::Matchers, SpecHelpers
  end


  ::RSpec.configure do |config|
    config.treat_symbols_as_metadata_keys_with_true_values = true
    # Make all Buildr methods accessible from test cases, and add various helper methods.
    config.include Buildr
    config.include SpecHelpers

    # Sandbox Buildr for each test.
    config.include Sandbox
  end

end
