assaf-buildr 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. data/CHANGELOG +887 -0
  2. data/DISCLAIMER +7 -0
  3. data/LICENSE +176 -0
  4. data/NOTICE +26 -0
  5. data/README.rdoc +146 -0
  6. data/Rakefile +62 -0
  7. data/_buildr +38 -0
  8. data/addon/buildr/antlr.rb +65 -0
  9. data/addon/buildr/cobertura.rb +236 -0
  10. data/addon/buildr/emma.rb +238 -0
  11. data/addon/buildr/hibernate.rb +142 -0
  12. data/addon/buildr/javacc.rb +85 -0
  13. data/addon/buildr/jdepend.rb +60 -0
  14. data/addon/buildr/jetty.rb +248 -0
  15. data/addon/buildr/jibx.rb +86 -0
  16. data/addon/buildr/nailgun.rb +817 -0
  17. data/addon/buildr/openjpa.rb +90 -0
  18. data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  19. data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  20. data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  21. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  22. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  23. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  24. data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  25. data/addon/buildr/xmlbeans.rb +93 -0
  26. data/bin/buildr +28 -0
  27. data/buildr.buildfile +53 -0
  28. data/buildr.gemspec +58 -0
  29. data/doc/css/default.css +228 -0
  30. data/doc/css/print.css +100 -0
  31. data/doc/css/syntax.css +52 -0
  32. data/doc/images/apache-incubator-logo.png +0 -0
  33. data/doc/images/buildr-hires.png +0 -0
  34. data/doc/images/buildr.png +0 -0
  35. data/doc/images/favicon.png +0 -0
  36. data/doc/images/growl-icon.tiff +0 -0
  37. data/doc/images/note.png +0 -0
  38. data/doc/images/project-structure.png +0 -0
  39. data/doc/images/tip.png +0 -0
  40. data/doc/images/zbuildr.tif +0 -0
  41. data/doc/pages/artifacts.textile +207 -0
  42. data/doc/pages/building.textile +240 -0
  43. data/doc/pages/contributing.textile +208 -0
  44. data/doc/pages/download.textile +62 -0
  45. data/doc/pages/extending.textile +175 -0
  46. data/doc/pages/getting_started.textile +273 -0
  47. data/doc/pages/index.textile +42 -0
  48. data/doc/pages/languages.textile +407 -0
  49. data/doc/pages/mailing_lists.textile +17 -0
  50. data/doc/pages/more_stuff.textile +286 -0
  51. data/doc/pages/packaging.textile +427 -0
  52. data/doc/pages/projects.textile +274 -0
  53. data/doc/pages/recipes.textile +103 -0
  54. data/doc/pages/settings_profiles.textile +274 -0
  55. data/doc/pages/testing.textile +212 -0
  56. data/doc/pages/troubleshooting.textile +103 -0
  57. data/doc/pages/whats_new.textile +323 -0
  58. data/doc/print.haml +51 -0
  59. data/doc/print.toc.yaml +29 -0
  60. data/doc/scripts/buildr-git.rb +412 -0
  61. data/doc/scripts/install-jruby.sh +44 -0
  62. data/doc/scripts/install-linux.sh +64 -0
  63. data/doc/scripts/install-osx.sh +52 -0
  64. data/doc/site.haml +56 -0
  65. data/doc/site.toc.yaml +47 -0
  66. data/etc/KEYS +151 -0
  67. data/etc/git-svn-authors +16 -0
  68. data/lib/buildr.rb +35 -0
  69. data/lib/buildr/core.rb +27 -0
  70. data/lib/buildr/core/application.rb +489 -0
  71. data/lib/buildr/core/application_cli.rb +139 -0
  72. data/lib/buildr/core/build.rb +311 -0
  73. data/lib/buildr/core/checks.rb +382 -0
  74. data/lib/buildr/core/common.rb +154 -0
  75. data/lib/buildr/core/compile.rb +596 -0
  76. data/lib/buildr/core/environment.rb +120 -0
  77. data/lib/buildr/core/filter.rb +362 -0
  78. data/lib/buildr/core/generate.rb +195 -0
  79. data/lib/buildr/core/help.rb +118 -0
  80. data/lib/buildr/core/progressbar.rb +156 -0
  81. data/lib/buildr/core/project.rb +892 -0
  82. data/lib/buildr/core/test.rb +715 -0
  83. data/lib/buildr/core/transports.rb +558 -0
  84. data/lib/buildr/core/util.rb +289 -0
  85. data/lib/buildr/groovy.rb +18 -0
  86. data/lib/buildr/groovy/bdd.rb +105 -0
  87. data/lib/buildr/groovy/compiler.rb +138 -0
  88. data/lib/buildr/ide.rb +19 -0
  89. data/lib/buildr/ide/eclipse.rb +212 -0
  90. data/lib/buildr/ide/idea.ipr.template +300 -0
  91. data/lib/buildr/ide/idea.rb +189 -0
  92. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  93. data/lib/buildr/ide/idea7x.rb +210 -0
  94. data/lib/buildr/java.rb +23 -0
  95. data/lib/buildr/java/ant.rb +92 -0
  96. data/lib/buildr/java/bdd.rb +449 -0
  97. data/lib/buildr/java/commands.rb +211 -0
  98. data/lib/buildr/java/compiler.rb +348 -0
  99. data/lib/buildr/java/deprecated.rb +141 -0
  100. data/lib/buildr/java/jruby.rb +117 -0
  101. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  102. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  103. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +119 -0
  104. data/lib/buildr/java/packaging.rb +713 -0
  105. data/lib/buildr/java/pom.rb +178 -0
  106. data/lib/buildr/java/rjb.rb +155 -0
  107. data/lib/buildr/java/test_result.rb +308 -0
  108. data/lib/buildr/java/tests.rb +324 -0
  109. data/lib/buildr/java/version_requirement.rb +172 -0
  110. data/lib/buildr/packaging.rb +21 -0
  111. data/lib/buildr/packaging/artifact.rb +730 -0
  112. data/lib/buildr/packaging/artifact_namespace.rb +972 -0
  113. data/lib/buildr/packaging/artifact_search.rb +140 -0
  114. data/lib/buildr/packaging/gems.rb +102 -0
  115. data/lib/buildr/packaging/package.rb +233 -0
  116. data/lib/buildr/packaging/tar.rb +104 -0
  117. data/lib/buildr/packaging/zip.rb +722 -0
  118. data/lib/buildr/resources/buildr.icns +0 -0
  119. data/lib/buildr/scala.rb +19 -0
  120. data/lib/buildr/scala/compiler.rb +109 -0
  121. data/lib/buildr/scala/tests.rb +203 -0
  122. data/rakelib/apache.rake +191 -0
  123. data/rakelib/changelog.rake +57 -0
  124. data/rakelib/doc.rake +103 -0
  125. data/rakelib/package.rake +73 -0
  126. data/rakelib/release.rake +65 -0
  127. data/rakelib/rspec.rake +83 -0
  128. data/rakelib/rubyforge.rake +53 -0
  129. data/rakelib/scm.rake +49 -0
  130. data/rakelib/setup.rake +86 -0
  131. data/rakelib/stage.rake +48 -0
  132. data/spec/addon/cobertura_spec.rb +77 -0
  133. data/spec/addon/emma_spec.rb +120 -0
  134. data/spec/addon/test_coverage_spec.rb +255 -0
  135. data/spec/core/application_spec.rb +412 -0
  136. data/spec/core/artifact_namespace_spec.rb +646 -0
  137. data/spec/core/build_spec.rb +415 -0
  138. data/spec/core/checks_spec.rb +537 -0
  139. data/spec/core/common_spec.rb +664 -0
  140. data/spec/core/compile_spec.rb +566 -0
  141. data/spec/core/generate_spec.rb +33 -0
  142. data/spec/core/project_spec.rb +754 -0
  143. data/spec/core/test_spec.rb +1091 -0
  144. data/spec/core/transport_spec.rb +500 -0
  145. data/spec/groovy/bdd_spec.rb +80 -0
  146. data/spec/groovy/compiler_spec.rb +239 -0
  147. data/spec/ide/eclipse_spec.rb +243 -0
  148. data/spec/java/ant.rb +28 -0
  149. data/spec/java/bdd_spec.rb +358 -0
  150. data/spec/java/compiler_spec.rb +446 -0
  151. data/spec/java/java_spec.rb +88 -0
  152. data/spec/java/packaging_spec.rb +1103 -0
  153. data/spec/java/tests_spec.rb +466 -0
  154. data/spec/packaging/archive_spec.rb +503 -0
  155. data/spec/packaging/artifact_spec.rb +754 -0
  156. data/spec/packaging/packaging_helper.rb +63 -0
  157. data/spec/packaging/packaging_spec.rb +589 -0
  158. data/spec/sandbox.rb +137 -0
  159. data/spec/scala/compiler_spec.rb +228 -0
  160. data/spec/scala/tests_spec.rb +215 -0
  161. data/spec/spec_helpers.rb +304 -0
  162. data/spec/version_requirement_spec.rb +123 -0
  163. metadata +369 -0
@@ -0,0 +1,178 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+
17
+ require 'xmlsimple'
18
+ require 'buildr/packaging'
19
+
20
+
21
+ module Buildr
22
+ class POM
23
+
24
+ POM_TO_SPEC_MAP = { :group=>"groupId", :id=>"artifactId", :type=>"type",
25
+ :version=>"version", :classifier=>"classifier", :scope=>"scope" }
26
+ SCOPES_TRANSITIVE = [nil, "compile", "runtime"]
27
+ SCOPES_WE_USE = SCOPES_TRANSITIVE + ["provided"]
28
+
29
+ # POM project as Hash (using XmlSimple).
30
+ attr_reader :project
31
+ # Parent POM if referenced by this POM.
32
+ attr_reader :parent
33
+
34
+ class << self
35
+
36
+ # :call-seq:
37
+ # POM.load(arg)
38
+ #
39
+ # Load new POM object form various kind of sources such as artifact, hash representing spec, filename, XML.
40
+ def load(source)
41
+ case source
42
+ when Hash
43
+ load(Buildr.artifact(source).pom)
44
+ when Artifact
45
+ pom = source.pom
46
+ pom.invoke
47
+ load(pom.to_s)
48
+ when Rake::FileTask
49
+ source.invoke
50
+ load(source.to_s)
51
+ when String
52
+ filename = File.expand_path(source)
53
+ unless pom = cache[filename]
54
+ trace "Loading m2 pom file from #{filename}"
55
+ pom = POM.new(IO.read(filename))
56
+ cache[filename] = pom
57
+ end
58
+ pom
59
+ else
60
+ raise ArgumentError, "Expecting Hash spec, Artifact, file name or file task"
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def cache()
67
+ @cache ||= {}
68
+ end
69
+
70
+ end
71
+
72
+ def initialize(xml) #:nodoc:
73
+ @project = XmlSimple.xml_in(xml)
74
+ @parent = POM.load(pom_to_hash(project["parent"].first).merge(:type=>'pom')) if project['parent']
75
+ end
76
+
77
+ # :call-seq:
78
+ # dependencies(scopes?) => artifacts
79
+ #
80
+ # Returns list of required dependencies as specified by the POM. You can specify which scopes
81
+ # to use (e.g. "compile", "runtime"); use +nil+ for dependencies with unspecified scope.
82
+ # The default scopes are +nil+, "compile" and "runtime" (aka SCOPES_WE_USE).
83
+ def dependencies(scopes = SCOPES_WE_USE)
84
+ #try to cache dependencies also
85
+ @depends_for_scopes ||= {}
86
+ unless depends = @depends_for_scopes[scopes]
87
+ declared = project["dependencies"].first["dependency"] rescue nil
88
+ depends = (declared || []).reject { |dep| value_of(dep["optional"]) =~ /true/ }.
89
+ map { |dep|
90
+ spec = pom_to_hash(dep, properties)
91
+ apply = managed(spec)
92
+ spec = apply.merge(spec) if apply
93
+
94
+ #calculate transitive dependencies
95
+ if scopes.include?(spec[:scope])
96
+ spec.delete(:scope)
97
+
98
+ exclusions = dep["exclusions"]["exclusion"] rescue nil
99
+ transitive_deps = POM.load(spec).dependencies(SCOPES_TRANSITIVE)
100
+ transitive_deps = transitive_deps.reject{|dep|
101
+ exclusions.find {|ex| dep.index("#{dep['groupdId'].first}:#{dep['artifactId'].first}:") == 0}
102
+ } if exclusions
103
+
104
+ [Artifact.to_spec(spec)] + transitive_deps
105
+ end
106
+ }.flatten.compact #.uniq_by{|spec| art = spec.split(':'); "#{art[0]}:#{art[1]}"}
107
+
108
+ @depends_for_scopes[scopes] = depends
109
+ end
110
+ depends
111
+ end
112
+
113
+ # :call-seq:
114
+ # properties() => hash
115
+ #
116
+ # Returns properties available to this POM as hash. Includes explicit properties and pom.xxx/project.xxx
117
+ # properties for groupId, artifactId, version and packaging.
118
+ def properties()
119
+ @properties ||= begin
120
+ pom = ["groupId", "artifactId", "version", "packaging"].inject({}) { |hash, key|
121
+ value = project[key] || (parent ? parent.project[key] : nil)
122
+ hash["pom.#{key}"] = hash["project.#{key}"] = value_of(value) if value
123
+ hash
124
+ }
125
+ props = project["properties"].first rescue {}
126
+ props = props.inject({}) { |mapped, pair| mapped[pair.first] = value_of(pair.last, pom) ; mapped }
127
+ (parent ? parent.properties.merge(props) : props).merge(pom)
128
+ end
129
+ end
130
+
131
+ # :call-seq:
132
+ # managed() => hash
133
+ # managed(hash) => hash
134
+ #
135
+ # The first form returns all the managed dependencies specified by this POM in dependencyManagement.
136
+ # The second form uses a single spec hash and expands it from the current/parent POM. Used to determine
137
+ # the version number if specified in dependencyManagement instead of dependencies.
138
+ def managed(spec = nil)
139
+ if spec
140
+ managed.detect { |dep| [:group, :id, :type, :classifier].all? { |key| spec[key] == dep[key] } } ||
141
+ (parent ? parent.managed(spec) : nil)
142
+ else
143
+ @managed ||= begin
144
+ managed = project["dependencyManagement"].first["dependencies"].first["dependency"] rescue nil
145
+ managed ? managed.map { |dep| pom_to_hash(dep, properties) } : []
146
+ end
147
+ end
148
+ end
149
+
150
+ private
151
+
152
+ # :call-seq:
153
+ # value_of(element) => string
154
+ # value_of(element, true) => string
155
+ #
156
+ # Returns the normalized text value of an element from its XmlSimple value. The second form performs
157
+ # property substitution.
158
+ def value_of(element, substitute = nil)
159
+ value = element.to_a.join.strip
160
+ substitute ? value.gsub(/\$\{([^}]+)\}/) { |key| substitute[$1] } : value
161
+ end
162
+
163
+ # :call-seq:
164
+ # pom_to_hash(element) => hash
165
+ # pom_to_hash(element, true) => hash
166
+ #
167
+ # Return the spec hash from an XmlSimple POM referencing element (e.g. project, parent, dependency).
168
+ # The second form performs property substitution.
169
+ def pom_to_hash(element, substitute = nil)
170
+ hash = POM_TO_SPEC_MAP.inject({}) { |spec, pair|
171
+ spec[pair.first] = value_of(element[pair.last], substitute) if element[pair.last]
172
+ spec
173
+ }
174
+ { :type=>"jar" }.merge(hash)
175
+ end
176
+
177
+ end
178
+ end
@@ -0,0 +1,155 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+
17
+ require 'rjb'
18
+
19
+
20
+ # Equivalent to Java system properties. For example:
21
+ # ENV_JAVA['java.version']
22
+ # ENV_JAVA['java.class.version']
23
+ ENV_JAVA = {}
24
+
25
+
26
+ # Buildr runs along side a JVM, using either RJB or JRuby. The Java module allows
27
+ # you to access Java classes and create Java objects.
28
+ #
29
+ # Java classes are accessed as static methods on the Java module, for example:
30
+ # str = Java.java.lang.String.new('hai!')
31
+ # str.toUpperCase
32
+ # => 'HAI!'
33
+ # Java.java.lang.String.isInstance(str)
34
+ # => true
35
+ # Java.com.sun.tools.javac.Main.compile(args)
36
+ #
37
+ # The classpath attribute allows Buildr to add JARs and directories to the classpath,
38
+ # for example, we use it to load Ant and various Ant tasks, code generators, test
39
+ # frameworks, and so forth.
40
+ #
41
+ # When using an artifact specification, Buildr will automatically download and
42
+ # install the artifact before adding it to the classpath.
43
+ #
44
+ # For example, Ant is loaded as follows:
45
+ # Java.classpath << 'org.apache.ant:ant:jar:1.7.0'
46
+ #
47
+ # Artifacts can only be downloaded after the Buildfile has loaded, giving it
48
+ # a chance to specify which remote repositories to use, so adding to classpath
49
+ # does not by itself load any libraries. You must call Java.load before accessing
50
+ # any Java classes to give Buildr a chance to load the libraries specified in the
51
+ # classpath.
52
+ #
53
+ # When building an extension, make sure to follow these rules:
54
+ # 1. Add to the classpath when the extension is loaded (i.e. in module or class
55
+ # definition), so the first call to Java.load anywhere in the code will include
56
+ # the libraries you specify.
57
+ # 2. Call Java.load once before accessing any Java classes, allowing Buildr to
58
+ # set up the classpath.
59
+ # 3. Only call Java.load when invoked, otherwise you may end up loading the JVM
60
+ # with a partial classpath, or before all remote repositories are listed.
61
+ # 4. Check on a clean build with empty local repository.
62
+ module Java
63
+
64
+ module Package #:nodoc:
65
+
66
+ def method_missing(sym, *args, &block)
67
+ raise ArgumentError, 'No arguments expected' unless args.empty?
68
+ name = "#{@name}.#{sym}"
69
+ return ::Rjb.import(name) if sym.to_s =~ /^[[:upper:]]/
70
+ ::Java.send :__package__, name
71
+ end
72
+
73
+ end
74
+
75
+ # On OS X we know where the default JDK is. We can try to guess for other OS.
76
+ # We set JAVA_HOME early so we can use it without calling Java.load first.
77
+ ENV['JAVA_HOME'] ||= '/System/Library/Frameworks/JavaVM.framework/Home' if Config::CONFIG['host_os'] =~ /darwin/i
78
+
79
+ class << self
80
+
81
+ # Returns the classpath, an array listing directories, JAR files and
82
+ # artifacts. Use when loading the extension to add any additional
83
+ # libraries used by that extension.
84
+ #
85
+ # For example, Ant is loaded as follows:
86
+ # Java.classpath << 'org.apache.ant:ant:jar:1.7.0'
87
+ def classpath
88
+ @classpath ||= []
89
+ end
90
+
91
+ # Most platforms requires tools.jar to be on the classpath, tools.jar contains the
92
+ # Java compiler (OS X and AIX are two exceptions we know about, may be more).
93
+ # Guess where tools.jar is from JAVA_HOME, which hopefully points to the JDK,
94
+ # but maybe the JRE. Return nil if not found.
95
+ def tools_jar #:nodoc:
96
+ @tools_jar ||= begin
97
+ home = ENV['JAVA_HOME'] or fail 'Are we forgetting something? JAVA_HOME not set.'
98
+ ['lib/tools.jar', '../lib/tools.jar'].map { |path| File.expand_path(path, home) }.
99
+ find { |path| File.exist?(path) }
100
+ end
101
+ end
102
+
103
+ # Loads the JVM and all the libraries listed on the classpath. Call this
104
+ # method before accessing any Java class, but only call it from methods
105
+ # used in the build, giving the Buildfile a chance to load all extensions
106
+ # that append to the classpath and specify which remote repositories to use.
107
+ def load
108
+ return self if @loaded
109
+ classpath << tools_jar if tools_jar
110
+
111
+ classpath.map! { |path| Proc === path ? path.call : path }
112
+ cp = Buildr.artifacts(classpath).map(&:to_s).each { |path| file(path).invoke }
113
+ java_opts = (ENV['JAVA_OPTS'] || ENV['JAVA_OPTIONS']).to_s.split
114
+ ::Rjb.load cp.join(File::PATH_SEPARATOR), java_opts
115
+
116
+ props = ::Rjb.import('java.lang.System').getProperties
117
+ enum = props.propertyNames
118
+ while enum.hasMoreElements
119
+ name = enum.nextElement.toString
120
+ ENV_JAVA[name] = props.getProperty(name)
121
+ end
122
+ @loaded = true
123
+ self
124
+ end
125
+
126
+ def method_missing(sym, *args, &block) #:nodoc:
127
+ raise ArgumentError, 'No arguments expected' unless args.empty?
128
+ name = sym.to_s
129
+ return ::Rjb.import(name) if name =~ /^[[:upper:]]/
130
+ __package__ name
131
+ end
132
+
133
+ private
134
+
135
+ def __package__(name) #:nodoc:
136
+ const = name.split('.').map { |part| part.gsub(/^./) { |char| char.upcase } }.join
137
+ return const_get(const) if const_defined?(const)
138
+ package = Module.new
139
+ package.extend Package
140
+ package.instance_variable_set :@name, name
141
+ const_set(const, package)
142
+ end
143
+
144
+ end
145
+
146
+ end
147
+
148
+
149
+ class Array
150
+ # Converts a Ruby array into a typed Java array, argument specifies the element type.
151
+ # This is necessary for JRuby and causes no harm on RJB.
152
+ def to_java(cls)
153
+ map { |item| cls.new(item) }
154
+ end
155
+ end
@@ -0,0 +1,308 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ require 'yaml'
17
+
18
+ module Buildr #:nodoc:
19
+ module TestFramework
20
+
21
+ # A class used by buildr for jruby based frameworks, so that buildr can know
22
+ # which tests succeeded/failed.
23
+ class TestResult
24
+
25
+ class Error < ::Exception
26
+ attr_reader :message, :backtrace
27
+ def initialize(message, backtrace)
28
+ @message = message
29
+ @backtrace = backtrace
30
+ set_backtrace backtrace
31
+ end
32
+
33
+ def self.dump_yaml(file, e)
34
+ require 'fileutils'
35
+ FileUtils.mkdir_p(File.dirname(file))
36
+ File.open(file, 'w') { |f| f.puts(YAML.dump(Error.new(e.message, e.backtrace))) }
37
+ end
38
+
39
+ def self.guard(file)
40
+ begin
41
+ yield
42
+ rescue
43
+ dump_yaml(file)
44
+ end
45
+ end
46
+ end
47
+
48
+ attr_accessor :failed, :succeeded
49
+
50
+ def initialize
51
+ @failed, @succeeded = [], []
52
+ end
53
+
54
+ # An Rspec formatter used by buildr
55
+ class YamlFormatter
56
+ attr_reader :result
57
+
58
+ attr_accessor :example_group, :options, :where
59
+
60
+ def initialize(options, where)
61
+ @options = options
62
+ @where = where
63
+ @result = Hash.new
64
+ @result[:succeeded] = []
65
+ @result[:failed] = []
66
+ end
67
+
68
+ %w[ example_started
69
+ start_dump dump_failure dump_summary dump_pending ].each do |meth|
70
+ module_eval "def #{meth}(*args); end"
71
+ end
72
+
73
+ def add_example_group(example_group)
74
+ @example_group = example_group
75
+ end
76
+
77
+ def example_passed(example)
78
+ end
79
+
80
+ def example_pending(example, counter, failure)
81
+ end
82
+
83
+ def example_failed(example, counter, failure)
84
+ if example_group.respond_to?(:spec_path)
85
+ result.failed << example_group.spec_path.gsub(/:\d+$/, '')
86
+ else
87
+ path = path_from_bt(failure.exception.backtrace)
88
+ result.failed << path if path
89
+ end
90
+ end
91
+
92
+ def start(example_count)
93
+ @result = TestResult.new
94
+ end
95
+
96
+ def path_from_bt(ary)
97
+ files = options.files
98
+ test = nil
99
+ ary.find do |bt|
100
+ bt = bt.split(':').first.strip
101
+ test = bt if files.include?(bt)
102
+ end
103
+ test
104
+ end
105
+
106
+ def close
107
+ files = options.files
108
+ result.succeeded = files - result.failed
109
+
110
+ FileUtils.mkdir_p(File.dirname(where))
111
+ File.open(where, 'w') { |f| f.puts YAML.dump(result) }
112
+ end
113
+ end # YamlFormatter
114
+
115
+ # A JtestR ResultHandler
116
+ # Using this handler we can use RSpec formatters, like html/ci_reporter with JtestR
117
+ # Created for YamlFormatter
118
+ class RSpecResultHandler
119
+
120
+ # Workaround for http://jira.codehaus.org/browse/JTESTR-68
121
+ module TestNGResultHandlerMixin
122
+ def onTestSuccess(test_result)
123
+ @result_handler.succeed_single(test_result.name)
124
+ end
125
+ end
126
+
127
+ class BacktraceTweaker
128
+ attr_reader :ignore_patterns
129
+ def initialize
130
+ @ignore_patterns = ::Spec::Runner::QuietBacktraceTweaker::IGNORE_PATTERNS.dup
131
+ # ignore jruby/jtestr backtrace
132
+ ignore_patterns << /org\.jruby\.javasupport\.JavaMethod\./
133
+ ignore_patterns << /jtestr.*\.jar!/i << /runner\.rb/
134
+ end
135
+
136
+ def clean_up_double_slashes(line)
137
+ line.gsub!('//','/')
138
+ end
139
+
140
+ def tweak_backtrace(error)
141
+ return if error.backtrace.nil?
142
+ error.backtrace.collect! do |line|
143
+ clean_up_double_slashes(line)
144
+ ignore_patterns.each do |ignore|
145
+ if line =~ ignore
146
+ line = nil
147
+ break
148
+ end
149
+ end
150
+ line
151
+ end
152
+ error.backtrace.compact!
153
+ end
154
+ end
155
+
156
+ class << self
157
+ # an rspec reporter used to proxy events to rspec formatters
158
+ attr_reader :reporter
159
+
160
+ def init(argv = [], out = STDOUT, err = STDERR)
161
+ ::JtestR::TestNGResultHandler.module_eval { include TestNGResultHandlerMixin }
162
+ rspec_parser = ::Spec::Runner::OptionParser.new(err, out)
163
+ rspec_parser.order!(argv)
164
+ rspec_parser.options.backtrace_tweaker = BacktraceTweaker.new
165
+ @reporter = Spec::Runner::Reporter.new(rspec_parser.options)
166
+ end
167
+
168
+ def before
169
+ reporter.start(reporter.options.files.size)
170
+ end
171
+
172
+ def after
173
+ reporter.end
174
+ reporter.dump
175
+ end
176
+ end
177
+
178
+ module ExampleMethods
179
+ attr_accessor :name, :description, :__full_description
180
+ end
181
+
182
+ def reporter
183
+ self.class.reporter
184
+ end
185
+
186
+ attr_accessor :example_group, :current_example, :current_failure
187
+
188
+ def initialize(name, desc, *args)
189
+ self.example_group = ::Spec::Example::ExampleGroup.new(desc)
190
+ example_group.extend ExampleMethods
191
+ example_group.name = name.to_s
192
+ if example_group.name[/Spec/]
193
+ example_group.description = desc.to_s
194
+ else
195
+ example_group.description = name.to_s
196
+ end
197
+ reporter.add_example_group(example_group)
198
+ end
199
+
200
+ def starting
201
+ end
202
+
203
+ def ending
204
+ end
205
+
206
+ def add_fault(fault)
207
+ self.current_failure = fault
208
+ end
209
+
210
+ def add_pending(pending)
211
+ end
212
+
213
+ def starting_single(name = nil)
214
+ self.current_failure = nil
215
+ self.current_example = Object.new
216
+ current_example.extend ::Spec::Example::ExampleMethods
217
+ current_example.extend ExampleMethods
218
+ name = name.to_s
219
+ name[/\((pen?ding|error|failure|success)\)?$/]
220
+ name = $`
221
+ current_example.description = name
222
+ if example_group.name[/Spec/]
223
+ current_example.__full_description = "#{example_group.description} #{name}"
224
+ else
225
+ current_example.__full_description = "#{example_group.name}: #{name}"
226
+ end
227
+ reporter.example_started(current_example)
228
+ #puts "STARTED #{name} #{current_example.__full_description}"
229
+ end
230
+
231
+ def succeed_single(name = nil)
232
+ #puts "SUCC SINGLE #{name}"
233
+ reporter.example_finished(current_example, nil)
234
+ end
235
+
236
+ def fail_single(name = nil)
237
+ #puts "FAIL SINGLE #{name}"
238
+ reporter.example_finished(current_example, current_error)
239
+ end
240
+
241
+ def error_single(name = nil)
242
+ #puts "ERR SINGLE #{name}"
243
+ reporter.example_finished(current_example, current_error)
244
+ end
245
+
246
+ def pending_single(name = nil)
247
+ #puts "PEND SINGLE #{name}"
248
+ error = ::Spec::Example::ExamplePendingError.new(name)
249
+ reporter.example_finished(current_example, error)
250
+ end
251
+
252
+ private
253
+ def current_error(fault = current_failure)
254
+ case fault
255
+ when nil
256
+ nil
257
+ when Test::Unit::Failure
258
+ Error.new(fault.message, fault.location)
259
+ when Test::Unit::Error
260
+ if fault.exception.is_a?(NativeException)
261
+ exception = fault.exception.cause
262
+ bt = exception.stack_trace.to_a
263
+ else
264
+ exception = fault.exception
265
+ bt = exception.backtrace
266
+ end
267
+ Error.new(exception.message, bt)
268
+ when Expectations::Results::Error
269
+ fault.exception
270
+ when Spec::Runner::Reporter::Failure
271
+ ex = fault.exception
272
+ fault.example.instance_variable_get(:@_implementation).to_s =~ /@(.+:\d+)/
273
+ Error.new(ex.message, [$1.to_s] + ex.backtrace)
274
+ when Expectations::Results
275
+ file = fault.file
276
+ line = fault.line
277
+ Error.new(fault.message, ["#{fault.file}:#{fault.line}"])
278
+ else
279
+ if fault.respond_to?(:test_header)
280
+ fault.test_header[/\((.+)\)/]
281
+ test_cls, test_meth = $1.to_s, $`.to_s
282
+ exception = fault.exception
283
+ (class << exception; self; end).module_eval do
284
+ define_method(:backtrace) do
285
+ (["#{test_cls}:in `#{test_meth}'"] + stackTrace).map { |s| s.to_s }
286
+ end
287
+ end
288
+ exception
289
+ elsif fault.respond_to?(:method)
290
+ test_cls, test_meth = fault.method.test_class.name, fault.method.method_name
291
+ exception = fault.throwable
292
+ (class << exception; self; end).module_eval do
293
+ define_method(:backtrace) do
294
+ (["#{test_cls}:in `#{test_meth}'"] + stackTrace).map { |s| s.to_s }
295
+ end
296
+ end
297
+ exception
298
+ else
299
+ raise "Cannot handle fault #{fault.class}: #{fault.inspect}"
300
+ end
301
+ end
302
+ end
303
+
304
+ end # RSpecResultHandler
305
+
306
+ end # TestResult
307
+ end
308
+ end