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