mack 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (477) hide show
  1. data/CHANGELOG +22 -1
  2. data/bin/mack +3 -0
  3. data/bin/mackery-console +4 -0
  4. data/bin/mackery-server +21 -4
  5. data/lib/gems.rb +15 -0
  6. data/lib/gems/abstract-1.0.0/lib/abstract.rb +75 -0
  7. data/lib/gems/builder-2.1.2/lib/blankslate.rb +113 -0
  8. data/lib/gems/builder-2.1.2/lib/builder.rb +13 -0
  9. data/lib/gems/builder-2.1.2/lib/builder/blankslate.rb +20 -0
  10. data/lib/gems/builder-2.1.2/lib/builder/css.rb +250 -0
  11. data/lib/gems/builder-2.1.2/lib/builder/xchar.rb +115 -0
  12. data/lib/gems/builder-2.1.2/lib/builder/xmlbase.rb +139 -0
  13. data/lib/gems/builder-2.1.2/lib/builder/xmlevents.rb +63 -0
  14. data/lib/gems/builder-2.1.2/lib/builder/xmlmarkup.rb +328 -0
  15. data/lib/gems/configatron-2.1.5/lib/configatron.rb +6 -0
  16. data/lib/gems/configatron-2.1.5/lib/configatron/configatron.rb +52 -0
  17. data/lib/gems/configatron-2.1.5/lib/configatron/errors.rb +7 -0
  18. data/lib/gems/configatron-2.1.5/lib/configatron/kernel.rb +8 -0
  19. data/lib/gems/configatron-2.1.5/lib/configatron/store.rb +224 -0
  20. data/lib/gems/daemons-1.0.10/lib/daemons.rb +283 -0
  21. data/lib/gems/daemons-1.0.10/lib/daemons/application.rb +372 -0
  22. data/lib/gems/daemons-1.0.10/lib/daemons/application_group.rb +152 -0
  23. data/lib/gems/daemons-1.0.10/lib/daemons/cmdline.rb +117 -0
  24. data/lib/gems/daemons-1.0.10/lib/daemons/controller.rb +134 -0
  25. data/lib/gems/daemons-1.0.10/lib/daemons/daemonize.rb +263 -0
  26. data/lib/gems/daemons-1.0.10/lib/daemons/exceptions.rb +28 -0
  27. data/lib/gems/daemons-1.0.10/lib/daemons/monitor.rb +127 -0
  28. data/lib/gems/daemons-1.0.10/lib/daemons/pid.rb +101 -0
  29. data/lib/gems/daemons-1.0.10/lib/daemons/pidfile.rb +111 -0
  30. data/lib/gems/daemons-1.0.10/lib/daemons/pidmem.rb +10 -0
  31. data/lib/gems/flexmock-0.8.3/lib/flexmock.rb +13 -0
  32. data/lib/gems/flexmock-0.8.3/lib/flexmock/argument_matchers.rb +57 -0
  33. data/lib/gems/flexmock-0.8.3/lib/flexmock/argument_types.rb +42 -0
  34. data/lib/gems/flexmock-0.8.3/lib/flexmock/base.rb +24 -0
  35. data/lib/gems/flexmock-0.8.3/lib/flexmock/composite.rb +10 -0
  36. data/lib/gems/flexmock-0.8.3/lib/flexmock/core.rb +218 -0
  37. data/lib/gems/flexmock-0.8.3/lib/flexmock/core_class_methods.rb +83 -0
  38. data/lib/gems/flexmock-0.8.3/lib/flexmock/default_framework_adapter.rb +31 -0
  39. data/lib/gems/flexmock-0.8.3/lib/flexmock/deprecated_methods.rb +62 -0
  40. data/lib/gems/flexmock-0.8.3/lib/flexmock/errors.rb +23 -0
  41. data/lib/gems/flexmock-0.8.3/lib/flexmock/expectation.rb +476 -0
  42. data/lib/gems/flexmock-0.8.3/lib/flexmock/expectation_director.rb +87 -0
  43. data/lib/gems/flexmock-0.8.3/lib/flexmock/mock_container.rb +321 -0
  44. data/lib/gems/flexmock-0.8.3/lib/flexmock/noop.rb +13 -0
  45. data/lib/gems/flexmock-0.8.3/lib/flexmock/ordering.rb +51 -0
  46. data/lib/gems/flexmock-0.8.3/lib/flexmock/partial_mock.rb +291 -0
  47. data/lib/gems/flexmock-0.8.3/lib/flexmock/rails.rb +15 -0
  48. data/lib/gems/flexmock-0.8.3/lib/flexmock/rails/view_mocking.rb +102 -0
  49. data/lib/gems/flexmock-0.8.3/lib/flexmock/recorder.rb +71 -0
  50. data/lib/gems/flexmock-0.8.3/lib/flexmock/rspec.rb +34 -0
  51. data/lib/gems/flexmock-0.8.3/lib/flexmock/test_unit.rb +32 -0
  52. data/lib/gems/flexmock-0.8.3/lib/flexmock/test_unit_integration.rb +53 -0
  53. data/lib/gems/flexmock-0.8.3/lib/flexmock/undefined.rb +50 -0
  54. data/lib/gems/flexmock-0.8.3/lib/flexmock/validators.rb +77 -0
  55. data/lib/gems/genosaurus-1.2.4/lib/genosaurus.rb +233 -0
  56. data/lib/gems/lockfile-1.4.3/bin/rlock +360 -0
  57. data/lib/gems/lockfile-1.4.3/bin/rlock-1.4.3 +360 -0
  58. data/lib/gems/lockfile-1.4.3/lib/lockfile-1.4.3.rb +564 -0
  59. data/lib/gems/lockfile-1.4.3/lib/lockfile.rb +564 -0
  60. data/lib/gems/logging-0.9.4/data/bad_logging_1.rb +13 -0
  61. data/lib/gems/logging-0.9.4/data/bad_logging_2.rb +21 -0
  62. data/lib/gems/logging-0.9.4/data/logging.rb +42 -0
  63. data/lib/gems/logging-0.9.4/data/logging.yaml +63 -0
  64. data/lib/gems/logging-0.9.4/data/simple_logging.rb +13 -0
  65. data/lib/gems/logging-0.9.4/lib/logging.rb +404 -0
  66. data/lib/gems/logging-0.9.4/lib/logging/appender.rb +300 -0
  67. data/lib/gems/logging-0.9.4/lib/logging/appenders/console.rb +62 -0
  68. data/lib/gems/logging-0.9.4/lib/logging/appenders/email.rb +130 -0
  69. data/lib/gems/logging-0.9.4/lib/logging/appenders/file.rb +54 -0
  70. data/lib/gems/logging-0.9.4/lib/logging/appenders/growl.rb +197 -0
  71. data/lib/gems/logging-0.9.4/lib/logging/appenders/io.rb +80 -0
  72. data/lib/gems/logging-0.9.4/lib/logging/appenders/rolling_file.rb +291 -0
  73. data/lib/gems/logging-0.9.4/lib/logging/appenders/syslog.rb +201 -0
  74. data/lib/gems/logging-0.9.4/lib/logging/config/configurator.rb +190 -0
  75. data/lib/gems/logging-0.9.4/lib/logging/config/yaml_configurator.rb +195 -0
  76. data/lib/gems/logging-0.9.4/lib/logging/layout.rb +110 -0
  77. data/lib/gems/logging-0.9.4/lib/logging/layouts/basic.rb +34 -0
  78. data/lib/gems/logging-0.9.4/lib/logging/layouts/pattern.rb +291 -0
  79. data/lib/gems/logging-0.9.4/lib/logging/log_event.rb +49 -0
  80. data/lib/gems/logging-0.9.4/lib/logging/logger.rb +490 -0
  81. data/lib/gems/logging-0.9.4/lib/logging/repository.rb +172 -0
  82. data/lib/gems/logging-0.9.4/lib/logging/root_logger.rb +61 -0
  83. data/lib/gems/logging-0.9.4/lib/logging/stats.rb +278 -0
  84. data/lib/gems/logging-0.9.4/lib/logging/utils.rb +130 -0
  85. data/lib/gems/rack-0.4.0/bin/rackup +172 -0
  86. data/lib/gems/rack-0.4.0/lib/rack.rb +81 -0
  87. data/lib/gems/rack-0.4.0/lib/rack/adapter/camping.rb +22 -0
  88. data/lib/gems/rack-0.4.0/lib/rack/auth/abstract/handler.rb +28 -0
  89. data/lib/gems/rack-0.4.0/lib/rack/auth/abstract/request.rb +37 -0
  90. data/lib/gems/rack-0.4.0/lib/rack/auth/basic.rb +58 -0
  91. data/lib/gems/rack-0.4.0/lib/rack/auth/digest/md5.rb +124 -0
  92. data/lib/gems/rack-0.4.0/lib/rack/auth/digest/nonce.rb +51 -0
  93. data/lib/gems/rack-0.4.0/lib/rack/auth/digest/params.rb +55 -0
  94. data/lib/gems/rack-0.4.0/lib/rack/auth/digest/request.rb +40 -0
  95. data/lib/gems/rack-0.4.0/lib/rack/auth/openid.rb +437 -0
  96. data/lib/gems/rack-0.4.0/lib/rack/builder.rb +56 -0
  97. data/lib/gems/rack-0.4.0/lib/rack/cascade.rb +36 -0
  98. data/lib/gems/rack-0.4.0/lib/rack/commonlogger.rb +61 -0
  99. data/lib/gems/rack-0.4.0/lib/rack/deflater.rb +63 -0
  100. data/lib/gems/rack-0.4.0/lib/rack/directory.rb +158 -0
  101. data/lib/gems/rack-0.4.0/lib/rack/file.rb +116 -0
  102. data/lib/gems/rack-0.4.0/lib/rack/handler.rb +44 -0
  103. data/lib/gems/rack-0.4.0/lib/rack/handler/cgi.rb +57 -0
  104. data/lib/gems/rack-0.4.0/lib/rack/handler/evented_mongrel.rb +8 -0
  105. data/lib/gems/rack-0.4.0/lib/rack/handler/fastcgi.rb +84 -0
  106. data/lib/gems/rack-0.4.0/lib/rack/handler/lsws.rb +52 -0
  107. data/lib/gems/rack-0.4.0/lib/rack/handler/mongrel.rb +78 -0
  108. data/lib/gems/rack-0.4.0/lib/rack/handler/scgi.rb +57 -0
  109. data/lib/gems/rack-0.4.0/lib/rack/handler/webrick.rb +57 -0
  110. data/lib/gems/rack-0.4.0/lib/rack/lint.rb +401 -0
  111. data/lib/gems/rack-0.4.0/lib/rack/lobster.rb +65 -0
  112. data/lib/gems/rack-0.4.0/lib/rack/mock.rb +160 -0
  113. data/lib/gems/rack-0.4.0/lib/rack/recursive.rb +57 -0
  114. data/lib/gems/rack-0.4.0/lib/rack/reloader.rb +64 -0
  115. data/lib/gems/rack-0.4.0/lib/rack/request.rb +209 -0
  116. data/lib/gems/rack-0.4.0/lib/rack/response.rb +166 -0
  117. data/lib/gems/rack-0.4.0/lib/rack/session/abstract/id.rb +140 -0
  118. data/lib/gems/rack-0.4.0/lib/rack/session/cookie.rb +71 -0
  119. data/lib/gems/rack-0.4.0/lib/rack/session/memcache.rb +97 -0
  120. data/lib/gems/rack-0.4.0/lib/rack/session/pool.rb +73 -0
  121. data/lib/gems/rack-0.4.0/lib/rack/showexceptions.rb +344 -0
  122. data/lib/gems/rack-0.4.0/lib/rack/showstatus.rb +105 -0
  123. data/lib/gems/rack-0.4.0/lib/rack/static.rb +38 -0
  124. data/lib/gems/rack-0.4.0/lib/rack/urlmap.rb +48 -0
  125. data/lib/gems/rack-0.4.0/lib/rack/utils.rb +318 -0
  126. data/lib/gems/rcov-0.8.1.2.0/bin/rcov +1327 -0
  127. data/lib/gems/rcov-0.8.1.2.0/ext/rcovrt/callsite.c +242 -0
  128. data/lib/gems/rcov-0.8.1.2.0/ext/rcovrt/extconf.rb +11 -0
  129. data/lib/gems/rcov-0.8.1.2.0/ext/rcovrt/rcovrt.c +329 -0
  130. data/lib/gems/rcov-0.8.1.2.0/lib/rcov.rb +988 -0
  131. data/lib/gems/rcov-0.8.1.2.0/lib/rcov/lowlevel.rb +147 -0
  132. data/lib/gems/rcov-0.8.1.2.0/lib/rcov/rant.rb +87 -0
  133. data/lib/gems/rcov-0.8.1.2.0/lib/rcov/rcovtask.rb +156 -0
  134. data/lib/gems/rcov-0.8.1.2.0/lib/rcov/report.rb +1236 -0
  135. data/lib/gems/rcov-0.8.1.2.0/lib/rcov/version.rb +13 -0
  136. data/lib/gems/rspec-1.1.11/bin/autospec +4 -0
  137. data/lib/gems/rspec-1.1.11/bin/spec +4 -0
  138. data/lib/gems/rspec-1.1.11/lib/autotest/discover.rb +3 -0
  139. data/lib/gems/rspec-1.1.11/lib/autotest/rspec.rb +46 -0
  140. data/lib/gems/rspec-1.1.11/lib/spec.rb +32 -0
  141. data/lib/gems/rspec-1.1.11/lib/spec/adapters.rb +1 -0
  142. data/lib/gems/rspec-1.1.11/lib/spec/adapters/ruby_engine.rb +26 -0
  143. data/lib/gems/rspec-1.1.11/lib/spec/adapters/ruby_engine/mri.rb +8 -0
  144. data/lib/gems/rspec-1.1.11/lib/spec/adapters/ruby_engine/rubinius.rb +8 -0
  145. data/lib/gems/rspec-1.1.11/lib/spec/example.rb +12 -0
  146. data/lib/gems/rspec-1.1.11/lib/spec/example/before_and_after_hooks.rb +93 -0
  147. data/lib/gems/rspec-1.1.11/lib/spec/example/configuration.rb +167 -0
  148. data/lib/gems/rspec-1.1.11/lib/spec/example/errors.rb +30 -0
  149. data/lib/gems/rspec-1.1.11/lib/spec/example/example_group.rb +25 -0
  150. data/lib/gems/rspec-1.1.11/lib/spec/example/example_group_factory.rb +81 -0
  151. data/lib/gems/rspec-1.1.11/lib/spec/example/example_group_methods.rb +368 -0
  152. data/lib/gems/rspec-1.1.11/lib/spec/example/example_matcher.rb +44 -0
  153. data/lib/gems/rspec-1.1.11/lib/spec/example/example_methods.rb +105 -0
  154. data/lib/gems/rspec-1.1.11/lib/spec/example/module_reopening_fix.rb +21 -0
  155. data/lib/gems/rspec-1.1.11/lib/spec/example/pending.rb +18 -0
  156. data/lib/gems/rspec-1.1.11/lib/spec/example/shared_example_group.rb +52 -0
  157. data/lib/gems/rspec-1.1.11/lib/spec/expectations.rb +56 -0
  158. data/lib/gems/rspec-1.1.11/lib/spec/expectations/differs/default.rb +66 -0
  159. data/lib/gems/rspec-1.1.11/lib/spec/expectations/errors.rb +12 -0
  160. data/lib/gems/rspec-1.1.11/lib/spec/expectations/extensions.rb +2 -0
  161. data/lib/gems/rspec-1.1.11/lib/spec/expectations/extensions/object.rb +63 -0
  162. data/lib/gems/rspec-1.1.11/lib/spec/expectations/extensions/string_and_symbol.rb +17 -0
  163. data/lib/gems/rspec-1.1.11/lib/spec/expectations/handler.rb +52 -0
  164. data/lib/gems/rspec-1.1.11/lib/spec/extensions.rb +4 -0
  165. data/lib/gems/rspec-1.1.11/lib/spec/extensions/class.rb +24 -0
  166. data/lib/gems/rspec-1.1.11/lib/spec/extensions/main.rb +87 -0
  167. data/lib/gems/rspec-1.1.11/lib/spec/extensions/metaclass.rb +7 -0
  168. data/lib/gems/rspec-1.1.11/lib/spec/extensions/object.rb +6 -0
  169. data/lib/gems/rspec-1.1.11/lib/spec/interop/test.rb +12 -0
  170. data/lib/gems/rspec-1.1.11/lib/spec/interop/test/unit/autorunner.rb +6 -0
  171. data/lib/gems/rspec-1.1.11/lib/spec/interop/test/unit/testcase.rb +71 -0
  172. data/lib/gems/rspec-1.1.11/lib/spec/interop/test/unit/testresult.rb +6 -0
  173. data/lib/gems/rspec-1.1.11/lib/spec/interop/test/unit/testsuite_adapter.rb +34 -0
  174. data/lib/gems/rspec-1.1.11/lib/spec/interop/test/unit/ui/console/testrunner.rb +61 -0
  175. data/lib/gems/rspec-1.1.11/lib/spec/matchers.rb +162 -0
  176. data/lib/gems/rspec-1.1.11/lib/spec/matchers/be.rb +221 -0
  177. data/lib/gems/rspec-1.1.11/lib/spec/matchers/be_close.rb +37 -0
  178. data/lib/gems/rspec-1.1.11/lib/spec/matchers/change.rb +148 -0
  179. data/lib/gems/rspec-1.1.11/lib/spec/matchers/eql.rb +43 -0
  180. data/lib/gems/rspec-1.1.11/lib/spec/matchers/equal.rb +43 -0
  181. data/lib/gems/rspec-1.1.11/lib/spec/matchers/exist.rb +22 -0
  182. data/lib/gems/rspec-1.1.11/lib/spec/matchers/has.rb +34 -0
  183. data/lib/gems/rspec-1.1.11/lib/spec/matchers/have.rb +150 -0
  184. data/lib/gems/rspec-1.1.11/lib/spec/matchers/include.rb +77 -0
  185. data/lib/gems/rspec-1.1.11/lib/spec/matchers/match.rb +41 -0
  186. data/lib/gems/rspec-1.1.11/lib/spec/matchers/operator_matcher.rb +79 -0
  187. data/lib/gems/rspec-1.1.11/lib/spec/matchers/raise_error.rb +132 -0
  188. data/lib/gems/rspec-1.1.11/lib/spec/matchers/respond_to.rb +46 -0
  189. data/lib/gems/rspec-1.1.11/lib/spec/matchers/satisfy.rb +47 -0
  190. data/lib/gems/rspec-1.1.11/lib/spec/matchers/simple_matcher.rb +132 -0
  191. data/lib/gems/rspec-1.1.11/lib/spec/matchers/throw_symbol.rb +74 -0
  192. data/lib/gems/rspec-1.1.11/lib/spec/mocks.rb +200 -0
  193. data/lib/gems/rspec-1.1.11/lib/spec/mocks/argument_constraints.rb +165 -0
  194. data/lib/gems/rspec-1.1.11/lib/spec/mocks/argument_expectation.rb +49 -0
  195. data/lib/gems/rspec-1.1.11/lib/spec/mocks/error_generator.rb +84 -0
  196. data/lib/gems/rspec-1.1.11/lib/spec/mocks/errors.rb +10 -0
  197. data/lib/gems/rspec-1.1.11/lib/spec/mocks/extensions.rb +1 -0
  198. data/lib/gems/rspec-1.1.11/lib/spec/mocks/extensions/object.rb +3 -0
  199. data/lib/gems/rspec-1.1.11/lib/spec/mocks/framework.rb +15 -0
  200. data/lib/gems/rspec-1.1.11/lib/spec/mocks/message_expectation.rb +331 -0
  201. data/lib/gems/rspec-1.1.11/lib/spec/mocks/methods.rb +51 -0
  202. data/lib/gems/rspec-1.1.11/lib/spec/mocks/mock.rb +56 -0
  203. data/lib/gems/rspec-1.1.11/lib/spec/mocks/order_group.rb +29 -0
  204. data/lib/gems/rspec-1.1.11/lib/spec/mocks/proxy.rb +224 -0
  205. data/lib/gems/rspec-1.1.11/lib/spec/mocks/space.rb +28 -0
  206. data/lib/gems/rspec-1.1.11/lib/spec/mocks/spec_methods.rb +46 -0
  207. data/lib/gems/rspec-1.1.11/lib/spec/rake/spectask.rb +227 -0
  208. data/lib/gems/rspec-1.1.11/lib/spec/rake/verify_rcov.rb +52 -0
  209. data/lib/gems/rspec-1.1.11/lib/spec/runner.rb +213 -0
  210. data/lib/gems/rspec-1.1.11/lib/spec/runner/backtrace_tweaker.rb +56 -0
  211. data/lib/gems/rspec-1.1.11/lib/spec/runner/class_and_arguments_parser.rb +16 -0
  212. data/lib/gems/rspec-1.1.11/lib/spec/runner/command_line.rb +17 -0
  213. data/lib/gems/rspec-1.1.11/lib/spec/runner/drb_command_line.rb +20 -0
  214. data/lib/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb +59 -0
  215. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/base_formatter.rb +79 -0
  216. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/base_text_formatter.rb +126 -0
  217. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/failing_example_groups_formatter.rb +27 -0
  218. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/failing_examples_formatter.rb +20 -0
  219. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/html_formatter.rb +337 -0
  220. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/nested_text_formatter.rb +65 -0
  221. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/profile_formatter.rb +51 -0
  222. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/progress_bar_formatter.rb +34 -0
  223. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/snippet_extractor.rb +52 -0
  224. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/specdoc_formatter.rb +39 -0
  225. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/story/html_formatter.rb +174 -0
  226. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/story/plain_text_formatter.rb +194 -0
  227. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/story/progress_bar_formatter.rb +42 -0
  228. data/lib/gems/rspec-1.1.11/lib/spec/runner/formatter/text_mate_formatter.rb +16 -0
  229. data/lib/gems/rspec-1.1.11/lib/spec/runner/heckle_runner.rb +72 -0
  230. data/lib/gems/rspec-1.1.11/lib/spec/runner/heckle_runner_unsupported.rb +10 -0
  231. data/lib/gems/rspec-1.1.11/lib/spec/runner/option_parser.rb +205 -0
  232. data/lib/gems/rspec-1.1.11/lib/spec/runner/options.rb +320 -0
  233. data/lib/gems/rspec-1.1.11/lib/spec/runner/reporter.rb +167 -0
  234. data/lib/gems/rspec-1.1.11/lib/spec/runner/spec_parser.rb +71 -0
  235. data/lib/gems/rspec-1.1.11/lib/spec/story.rb +10 -0
  236. data/lib/gems/rspec-1.1.11/lib/spec/story/extensions.rb +3 -0
  237. data/lib/gems/rspec-1.1.11/lib/spec/story/extensions/main.rb +86 -0
  238. data/lib/gems/rspec-1.1.11/lib/spec/story/extensions/regexp.rb +9 -0
  239. data/lib/gems/rspec-1.1.11/lib/spec/story/extensions/string.rb +9 -0
  240. data/lib/gems/rspec-1.1.11/lib/spec/story/given_scenario.rb +14 -0
  241. data/lib/gems/rspec-1.1.11/lib/spec/story/runner.rb +59 -0
  242. data/lib/gems/rspec-1.1.11/lib/spec/story/runner/plain_text_story_runner.rb +48 -0
  243. data/lib/gems/rspec-1.1.11/lib/spec/story/runner/scenario_collector.rb +18 -0
  244. data/lib/gems/rspec-1.1.11/lib/spec/story/runner/scenario_runner.rb +54 -0
  245. data/lib/gems/rspec-1.1.11/lib/spec/story/runner/story_mediator.rb +137 -0
  246. data/lib/gems/rspec-1.1.11/lib/spec/story/runner/story_parser.rb +247 -0
  247. data/lib/gems/rspec-1.1.11/lib/spec/story/runner/story_runner.rb +70 -0
  248. data/lib/gems/rspec-1.1.11/lib/spec/story/scenario.rb +14 -0
  249. data/lib/gems/rspec-1.1.11/lib/spec/story/step.rb +70 -0
  250. data/lib/gems/rspec-1.1.11/lib/spec/story/step_group.rb +89 -0
  251. data/lib/gems/rspec-1.1.11/lib/spec/story/step_mother.rb +38 -0
  252. data/lib/gems/rspec-1.1.11/lib/spec/story/story.rb +39 -0
  253. data/lib/gems/rspec-1.1.11/lib/spec/story/world.rb +128 -0
  254. data/lib/gems/rspec-1.1.11/lib/spec/version.rb +13 -0
  255. data/lib/gems/rspec-1.1.11/plugins/mock_frameworks/flexmock.rb +23 -0
  256. data/lib/gems/rspec-1.1.11/plugins/mock_frameworks/mocha.rb +19 -0
  257. data/lib/gems/rspec-1.1.11/plugins/mock_frameworks/rr.rb +21 -0
  258. data/lib/gems/rspec-1.1.11/plugins/mock_frameworks/rspec.rb +20 -0
  259. data/lib/gems/rspec-1.1.11/rake_tasks/examples.rake +7 -0
  260. data/lib/gems/rspec-1.1.11/rake_tasks/examples_with_rcov.rake +9 -0
  261. data/lib/gems/rspec-1.1.11/rake_tasks/failing_examples_with_html.rake +9 -0
  262. data/lib/gems/rspec-1.1.11/rake_tasks/verify_rcov.rake +7 -0
  263. data/lib/gems/rspec-1.1.11/spec/README.jruby +15 -0
  264. data/lib/gems/rspec-1.1.11/spec/autotest/autotest_helper.rb +6 -0
  265. data/lib/gems/rspec-1.1.11/spec/autotest/autotest_matchers.rb +47 -0
  266. data/lib/gems/rspec-1.1.11/spec/autotest/discover_spec.rb +19 -0
  267. data/lib/gems/rspec-1.1.11/spec/autotest/rspec_spec.rb +150 -0
  268. data/lib/gems/rspec-1.1.11/spec/rspec_suite.rb +6 -0
  269. data/lib/gems/rspec-1.1.11/spec/ruby_forker.rb +13 -0
  270. data/lib/gems/rspec-1.1.11/spec/spec.opts +6 -0
  271. data/lib/gems/rspec-1.1.11/spec/spec/adapters/ruby_engine_spec.rb +16 -0
  272. data/lib/gems/rspec-1.1.11/spec/spec/example/configuration_spec.rb +296 -0
  273. data/lib/gems/rspec-1.1.11/spec/spec/example/example_group_class_definition_spec.rb +48 -0
  274. data/lib/gems/rspec-1.1.11/spec/spec/example/example_group_factory_spec.rb +165 -0
  275. data/lib/gems/rspec-1.1.11/spec/spec/example/example_group_methods_spec.rb +584 -0
  276. data/lib/gems/rspec-1.1.11/spec/spec/example/example_group_spec.rb +683 -0
  277. data/lib/gems/rspec-1.1.11/spec/spec/example/example_matcher_spec.rb +96 -0
  278. data/lib/gems/rspec-1.1.11/spec/spec/example/example_methods_spec.rb +169 -0
  279. data/lib/gems/rspec-1.1.11/spec/spec/example/example_runner_spec.rb +194 -0
  280. data/lib/gems/rspec-1.1.11/spec/spec/example/nested_example_group_spec.rb +71 -0
  281. data/lib/gems/rspec-1.1.11/spec/spec/example/pending_module_spec.rb +145 -0
  282. data/lib/gems/rspec-1.1.11/spec/spec/example/predicate_matcher_spec.rb +21 -0
  283. data/lib/gems/rspec-1.1.11/spec/spec/example/shared_example_group_spec.rb +281 -0
  284. data/lib/gems/rspec-1.1.11/spec/spec/example/subclassing_example_group_spec.rb +25 -0
  285. data/lib/gems/rspec-1.1.11/spec/spec/expectations/differs/default_spec.rb +127 -0
  286. data/lib/gems/rspec-1.1.11/spec/spec/expectations/extensions/object_spec.rb +95 -0
  287. data/lib/gems/rspec-1.1.11/spec/spec/expectations/fail_with_spec.rb +71 -0
  288. data/lib/gems/rspec-1.1.11/spec/spec/extensions/main_spec.rb +71 -0
  289. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/spec_that_fails.rb +10 -0
  290. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/spec_that_passes.rb +10 -0
  291. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/spec_with_errors.rb +10 -0
  292. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/spec_with_options_hash.rb +13 -0
  293. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/test_case_that_fails.rb +10 -0
  294. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/test_case_that_passes.rb +10 -0
  295. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/test_case_with_errors.rb +10 -0
  296. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb +38 -0
  297. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/spec_spec.rb +52 -0
  298. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/test_unit_spec_helper.rb +14 -0
  299. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/testcase_spec.rb +49 -0
  300. data/lib/gems/rspec-1.1.11/spec/spec/interop/test/unit/testsuite_adapter_spec.rb +9 -0
  301. data/lib/gems/rspec-1.1.11/spec/spec/matchers/be_close_spec.rb +39 -0
  302. data/lib/gems/rspec-1.1.11/spec/spec/matchers/be_spec.rb +248 -0
  303. data/lib/gems/rspec-1.1.11/spec/spec/matchers/change_spec.rb +329 -0
  304. data/lib/gems/rspec-1.1.11/spec/spec/matchers/description_generation_spec.rb +153 -0
  305. data/lib/gems/rspec-1.1.11/spec/spec/matchers/eql_spec.rb +28 -0
  306. data/lib/gems/rspec-1.1.11/spec/spec/matchers/equal_spec.rb +28 -0
  307. data/lib/gems/rspec-1.1.11/spec/spec/matchers/exist_spec.rb +57 -0
  308. data/lib/gems/rspec-1.1.11/spec/spec/matchers/handler_spec.rb +150 -0
  309. data/lib/gems/rspec-1.1.11/spec/spec/matchers/has_spec.rb +63 -0
  310. data/lib/gems/rspec-1.1.11/spec/spec/matchers/have_spec.rb +394 -0
  311. data/lib/gems/rspec-1.1.11/spec/spec/matchers/include_spec.rb +64 -0
  312. data/lib/gems/rspec-1.1.11/spec/spec/matchers/match_spec.rb +37 -0
  313. data/lib/gems/rspec-1.1.11/spec/spec/matchers/matcher_methods_spec.rb +78 -0
  314. data/lib/gems/rspec-1.1.11/spec/spec/matchers/mock_constraint_matchers_spec.rb +24 -0
  315. data/lib/gems/rspec-1.1.11/spec/spec/matchers/operator_matcher_spec.rb +191 -0
  316. data/lib/gems/rspec-1.1.11/spec/spec/matchers/raise_error_spec.rb +315 -0
  317. data/lib/gems/rspec-1.1.11/spec/spec/matchers/respond_to_spec.rb +54 -0
  318. data/lib/gems/rspec-1.1.11/spec/spec/matchers/satisfy_spec.rb +36 -0
  319. data/lib/gems/rspec-1.1.11/spec/spec/matchers/simple_matcher_spec.rb +93 -0
  320. data/lib/gems/rspec-1.1.11/spec/spec/matchers/throw_symbol_spec.rb +54 -0
  321. data/lib/gems/rspec-1.1.11/spec/spec/mocks/any_number_of_times_spec.rb +36 -0
  322. data/lib/gems/rspec-1.1.11/spec/spec/mocks/argument_expectation_spec.rb +23 -0
  323. data/lib/gems/rspec-1.1.11/spec/spec/mocks/at_least_spec.rb +97 -0
  324. data/lib/gems/rspec-1.1.11/spec/spec/mocks/at_most_spec.rb +93 -0
  325. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_10260_spec.rb +8 -0
  326. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_10263_spec.rb +24 -0
  327. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_11545_spec.rb +33 -0
  328. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_15719_spec.rb +30 -0
  329. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_496.rb +17 -0
  330. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_7611_spec.rb +19 -0
  331. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_7805_spec.rb +22 -0
  332. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_8165_spec.rb +31 -0
  333. data/lib/gems/rspec-1.1.11/spec/spec/mocks/bug_report_8302_spec.rb +26 -0
  334. data/lib/gems/rspec-1.1.11/spec/spec/mocks/failing_mock_argument_constraints_spec.rb +95 -0
  335. data/lib/gems/rspec-1.1.11/spec/spec/mocks/hash_including_matcher_spec.rb +53 -0
  336. data/lib/gems/rspec-1.1.11/spec/spec/mocks/mock_ordering_spec.rb +84 -0
  337. data/lib/gems/rspec-1.1.11/spec/spec/mocks/mock_space_spec.rb +54 -0
  338. data/lib/gems/rspec-1.1.11/spec/spec/mocks/mock_spec.rb +555 -0
  339. data/lib/gems/rspec-1.1.11/spec/spec/mocks/multiple_return_value_spec.rb +113 -0
  340. data/lib/gems/rspec-1.1.11/spec/spec/mocks/nil_expectation_warning_spec.rb +53 -0
  341. data/lib/gems/rspec-1.1.11/spec/spec/mocks/null_object_mock_spec.rb +54 -0
  342. data/lib/gems/rspec-1.1.11/spec/spec/mocks/once_counts_spec.rb +53 -0
  343. data/lib/gems/rspec-1.1.11/spec/spec/mocks/options_hash_spec.rb +35 -0
  344. data/lib/gems/rspec-1.1.11/spec/spec/mocks/partial_mock_spec.rb +149 -0
  345. data/lib/gems/rspec-1.1.11/spec/spec/mocks/partial_mock_using_mocks_directly_spec.rb +66 -0
  346. data/lib/gems/rspec-1.1.11/spec/spec/mocks/passing_mock_argument_constraints_spec.rb +130 -0
  347. data/lib/gems/rspec-1.1.11/spec/spec/mocks/precise_counts_spec.rb +52 -0
  348. data/lib/gems/rspec-1.1.11/spec/spec/mocks/record_messages_spec.rb +26 -0
  349. data/lib/gems/rspec-1.1.11/spec/spec/mocks/stub_spec.rb +188 -0
  350. data/lib/gems/rspec-1.1.11/spec/spec/mocks/twice_counts_spec.rb +67 -0
  351. data/lib/gems/rspec-1.1.11/spec/spec/package/bin_spec_spec.rb +22 -0
  352. data/lib/gems/rspec-1.1.11/spec/spec/runner/class_and_argument_parser_spec.rb +23 -0
  353. data/lib/gems/rspec-1.1.11/spec/spec/runner/command_line_spec.rb +141 -0
  354. data/lib/gems/rspec-1.1.11/spec/spec/runner/drb_command_line_spec.rb +97 -0
  355. data/lib/gems/rspec-1.1.11/spec/spec/runner/empty_file.txt +0 -0
  356. data/lib/gems/rspec-1.1.11/spec/spec/runner/examples.txt +2 -0
  357. data/lib/gems/rspec-1.1.11/spec/spec/runner/failed.txt +3 -0
  358. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/base_formatter_spec.rb +112 -0
  359. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb +45 -0
  360. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/failing_examples_formatter_spec.rb +33 -0
  361. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/html_formatted-1.8.4.html +365 -0
  362. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/html_formatted-1.8.5-jruby.html +387 -0
  363. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/html_formatted-1.8.5.html +371 -0
  364. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/html_formatted-1.8.6-jruby.html +381 -0
  365. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/html_formatted-1.8.6.html +370 -0
  366. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/html_formatter_spec.rb +61 -0
  367. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/nested_text_formatter_spec.rb +318 -0
  368. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/profile_formatter_spec.rb +65 -0
  369. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +155 -0
  370. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/snippet_extractor_spec.rb +18 -0
  371. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/spec_mate_formatter_spec.rb +103 -0
  372. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/specdoc_formatter_spec.rb +159 -0
  373. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/story/html_formatter_spec.rb +135 -0
  374. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb +600 -0
  375. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/story/progress_bar_formatter_spec.rb +82 -0
  376. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/text_mate_formatted-1.8.4.html +365 -0
  377. data/lib/gems/rspec-1.1.11/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html +370 -0
  378. data/lib/gems/rspec-1.1.11/spec/spec/runner/heckle_runner_spec.rb +78 -0
  379. data/lib/gems/rspec-1.1.11/spec/spec/runner/heckler_spec.rb +13 -0
  380. data/lib/gems/rspec-1.1.11/spec/spec/runner/noisy_backtrace_tweaker_spec.rb +45 -0
  381. data/lib/gems/rspec-1.1.11/spec/spec/runner/option_parser_spec.rb +421 -0
  382. data/lib/gems/rspec-1.1.11/spec/spec/runner/options_spec.rb +450 -0
  383. data/lib/gems/rspec-1.1.11/spec/spec/runner/output_one_time_fixture.rb +7 -0
  384. data/lib/gems/rspec-1.1.11/spec/spec/runner/output_one_time_fixture_runner.rb +8 -0
  385. data/lib/gems/rspec-1.1.11/spec/spec/runner/output_one_time_spec.rb +16 -0
  386. data/lib/gems/rspec-1.1.11/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +62 -0
  387. data/lib/gems/rspec-1.1.11/spec/spec/runner/reporter_spec.rb +238 -0
  388. data/lib/gems/rspec-1.1.11/spec/spec/runner/resources/a_bar.rb +0 -0
  389. data/lib/gems/rspec-1.1.11/spec/spec/runner/resources/a_foo.rb +0 -0
  390. data/lib/gems/rspec-1.1.11/spec/spec/runner/resources/a_spec.rb +1 -0
  391. data/lib/gems/rspec-1.1.11/spec/spec/runner/spec.opts +2 -0
  392. data/lib/gems/rspec-1.1.11/spec/spec/runner/spec_drb.opts +1 -0
  393. data/lib/gems/rspec-1.1.11/spec/spec/runner/spec_parser/spec_parser_fixture.rb +70 -0
  394. data/lib/gems/rspec-1.1.11/spec/spec/runner/spec_parser_spec.rb +85 -0
  395. data/lib/gems/rspec-1.1.11/spec/spec/runner/spec_spaced.opts +2 -0
  396. data/lib/gems/rspec-1.1.11/spec/spec/runner_spec.rb +11 -0
  397. data/lib/gems/rspec-1.1.11/spec/spec/spec_classes.rb +133 -0
  398. data/lib/gems/rspec-1.1.11/spec/spec/story/builders.rb +46 -0
  399. data/lib/gems/rspec-1.1.11/spec/spec/story/extensions/main_spec.rb +161 -0
  400. data/lib/gems/rspec-1.1.11/spec/spec/story/extensions_spec.rb +14 -0
  401. data/lib/gems/rspec-1.1.11/spec/spec/story/given_scenario_spec.rb +27 -0
  402. data/lib/gems/rspec-1.1.11/spec/spec/story/runner/plain_text_story_runner_spec.rb +90 -0
  403. data/lib/gems/rspec-1.1.11/spec/spec/story/runner/scenario_collector_spec.rb +27 -0
  404. data/lib/gems/rspec-1.1.11/spec/spec/story/runner/scenario_runner_spec.rb +214 -0
  405. data/lib/gems/rspec-1.1.11/spec/spec/story/runner/story_mediator_spec.rb +143 -0
  406. data/lib/gems/rspec-1.1.11/spec/spec/story/runner/story_parser_spec.rb +401 -0
  407. data/lib/gems/rspec-1.1.11/spec/spec/story/runner/story_runner_spec.rb +294 -0
  408. data/lib/gems/rspec-1.1.11/spec/spec/story/runner_spec.rb +93 -0
  409. data/lib/gems/rspec-1.1.11/spec/spec/story/scenario_spec.rb +18 -0
  410. data/lib/gems/rspec-1.1.11/spec/spec/story/step_group_spec.rb +157 -0
  411. data/lib/gems/rspec-1.1.11/spec/spec/story/step_mother_spec.rb +84 -0
  412. data/lib/gems/rspec-1.1.11/spec/spec/story/step_spec.rb +272 -0
  413. data/lib/gems/rspec-1.1.11/spec/spec/story/story_helper.rb +2 -0
  414. data/lib/gems/rspec-1.1.11/spec/spec/story/story_spec.rb +84 -0
  415. data/lib/gems/rspec-1.1.11/spec/spec/story/world_spec.rb +423 -0
  416. data/lib/gems/rspec-1.1.11/spec/spec_helper.rb +77 -0
  417. data/lib/gems/rspec-1.1.11/stories/all.rb +5 -0
  418. data/lib/gems/rspec-1.1.11/stories/configuration/before_blocks.story +21 -0
  419. data/lib/gems/rspec-1.1.11/stories/configuration/stories.rb +7 -0
  420. data/lib/gems/rspec-1.1.11/stories/example_groups/autogenerated_docstrings +45 -0
  421. data/lib/gems/rspec-1.1.11/stories/example_groups/example_group_with_should_methods +17 -0
  422. data/lib/gems/rspec-1.1.11/stories/example_groups/nested_groups +17 -0
  423. data/lib/gems/rspec-1.1.11/stories/example_groups/output +25 -0
  424. data/lib/gems/rspec-1.1.11/stories/example_groups/stories.rb +7 -0
  425. data/lib/gems/rspec-1.1.11/stories/helper.rb +6 -0
  426. data/lib/gems/rspec-1.1.11/stories/interop/examples_and_tests_together +30 -0
  427. data/lib/gems/rspec-1.1.11/stories/interop/stories.rb +7 -0
  428. data/lib/gems/rspec-1.1.11/stories/interop/test_case_with_should_methods +17 -0
  429. data/lib/gems/rspec-1.1.11/stories/mock_framework_integration/stories.rb +7 -0
  430. data/lib/gems/rspec-1.1.11/stories/mock_framework_integration/use_flexmock.story +9 -0
  431. data/lib/gems/rspec-1.1.11/stories/pending_stories/README +3 -0
  432. data/lib/gems/rspec-1.1.11/stories/resources/helpers/cmdline.rb +9 -0
  433. data/lib/gems/rspec-1.1.11/stories/resources/helpers/story_helper.rb +16 -0
  434. data/lib/gems/rspec-1.1.11/stories/resources/matchers/smart_match.rb +37 -0
  435. data/lib/gems/rspec-1.1.11/stories/resources/spec/before_blocks_example.rb +32 -0
  436. data/lib/gems/rspec-1.1.11/stories/resources/spec/example_group_with_should_methods.rb +12 -0
  437. data/lib/gems/rspec-1.1.11/stories/resources/spec/simple_spec.rb +8 -0
  438. data/lib/gems/rspec-1.1.11/stories/resources/spec/spec_with_flexmock.rb +18 -0
  439. data/lib/gems/rspec-1.1.11/stories/resources/steps/running_rspec.rb +50 -0
  440. data/lib/gems/rspec-1.1.11/stories/resources/stories/failing_story.rb +15 -0
  441. data/lib/gems/rspec-1.1.11/stories/resources/test/spec_and_test_together.rb +57 -0
  442. data/lib/gems/rspec-1.1.11/stories/resources/test/test_case_with_should_methods.rb +30 -0
  443. data/lib/gems/rspec-1.1.11/stories/stories/multiline_steps.story +23 -0
  444. data/lib/gems/rspec-1.1.11/stories/stories/steps/multiline_steps.rb +13 -0
  445. data/lib/gems/rspec-1.1.11/stories/stories/stories.rb +6 -0
  446. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/builder.js +136 -0
  447. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/controls.js +972 -0
  448. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/dragdrop.js +976 -0
  449. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/effects.js +1117 -0
  450. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/prototype.js +4140 -0
  451. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/rspec.js +149 -0
  452. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/scriptaculous.js +58 -0
  453. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/slider.js +276 -0
  454. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/sound.js +55 -0
  455. data/lib/gems/rspec-1.1.11/story_server/prototype/javascripts/unittest.js +568 -0
  456. data/lib/gems/rspec-1.1.11/story_server/prototype/lib/server.rb +24 -0
  457. data/lib/gems/rspec-1.1.11/story_server/prototype/stories.html +176 -0
  458. data/lib/gems/rspec-1.1.11/story_server/prototype/stylesheets/rspec.css +136 -0
  459. data/lib/gems/rspec-1.1.11/story_server/prototype/stylesheets/test.css +90 -0
  460. data/lib/mack/boot/configuration.rb +2 -0
  461. data/lib/mack/boot/console.rb +2 -0
  462. data/lib/mack/boot/gems.rb +6 -1
  463. data/lib/mack/boot/logging.rb +1 -1
  464. data/lib/mack/controller/request.rb +2 -55
  465. data/lib/mack/controller/request/date_time_parameter.rb +37 -0
  466. data/lib/mack/controller/request/parameters.rb +31 -0
  467. data/lib/mack/core_extensions/gem_kernel.rb +30 -0
  468. data/lib/mack/core_extensions/kernel.rb +31 -14
  469. data/lib/mack/routing/route_map.rb +19 -18
  470. data/lib/mack/routing/route_object.rb +14 -3
  471. data/lib/mack/routing/routes.rb +4 -0
  472. data/lib/mack/runner.rb +11 -0
  473. data/lib/mack/version.rb +1 -1
  474. data/lib/mack_app.rb +1 -26
  475. data/lib/mack_core.rb +2 -50
  476. data/lib/mack_tasks.rb +1 -32
  477. metadata +669 -90
@@ -0,0 +1,147 @@
1
+ # rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
2
+ #
3
+ # See LEGAL and LICENSE for licensing information.
4
+
5
+ require 'rcov/version'
6
+
7
+ module Rcov
8
+
9
+ # RCOV__ performs the low-level tracing of the execution, gathering code
10
+ # coverage information in the process. The C core made available through the
11
+ # rcovrt extension will be used if possible. Otherwise the functionality
12
+ # will be emulated using set_trace_func, but this is very expensive and
13
+ # will fail if other libraries (e.g. breakpoint) change the trace_func.
14
+ #
15
+ # Do not use this module; it is very low-level and subject to frequent
16
+ # changes. Rcov::CodeCoverageAnalyzer offers a much more convenient and
17
+ # stable interface.
18
+ module RCOV__
19
+ COVER = {}
20
+ CALLSITES = {}
21
+ DEFSITES = {}
22
+ pure_ruby_impl_needed = true
23
+ unless defined? $rcov_do_not_use_rcovrt
24
+ begin
25
+ require 'rcovrt'
26
+ abi = [0,0,0]
27
+ begin
28
+ abi = RCOV__.ABI
29
+ raise if abi[0] != RCOVRT_ABI[0] || abi[1] < RCOVRT_ABI[1]
30
+ pure_ruby_impl_needed = false
31
+ rescue
32
+ $stderr.puts <<-EOF
33
+ The rcovrt extension I found was built for a different version of rcov.
34
+ The required ABI is: #{RCOVRT_ABI.join(".")}
35
+ Your current rcovrt extension is: #{abi.join(".")}
36
+
37
+ Please delete rcovrt.{so,bundle,dll,...} and install the required one.
38
+ EOF
39
+ raise LoadError
40
+ end
41
+ rescue LoadError
42
+ $stderr.puts <<-EOF
43
+
44
+ Since the rcovrt extension couldn't be loaded, rcov will run in pure-Ruby
45
+ mode, which is about two orders of magnitude slower.
46
+
47
+ If you're on win32, you can find a pre-built extension (usable with recent
48
+ One Click Installer and mswin32 builds) at http://eigenclass.org/hiki.rb?rcov .
49
+
50
+ EOF
51
+ end
52
+ end
53
+
54
+ if pure_ruby_impl_needed
55
+ methods = %w[install_coverage_hook remove_coverage_hook reset_coverage
56
+ install_callsite_hook remove_callsite_hook reset_callsite
57
+ generate_coverage_info generate_callsite_info]
58
+ sklass = class << self; self end
59
+ (methods & sklass.instance_methods).each do |meth|
60
+ sklass.class_eval{ remove_method meth }
61
+ end
62
+
63
+ @coverage_hook_activated = @callsite_hook_activated = false
64
+
65
+ def self.install_coverage_hook # :nodoc:
66
+ install_common_hook
67
+ @coverage_hook_activated = true
68
+ end
69
+
70
+ def self.install_callsite_hook # :nodoc:
71
+ install_common_hook
72
+ @callsite_hook_activated = true
73
+ end
74
+
75
+ def self.install_common_hook # :nodoc:
76
+ set_trace_func lambda {|event, file, line, id, binding, klass|
77
+ next unless SCRIPT_LINES__.has_key? file
78
+ case event
79
+ when 'call'
80
+ if @callsite_hook_activated
81
+ receiver = eval("self", binding)
82
+ klass = class << klass; self end unless klass === receiver
83
+ begin
84
+ DEFSITES[[klass.to_s, id.to_s]] = [file, line]
85
+ rescue Exception
86
+ end
87
+ caller_arr = self.format_backtrace_array(caller[1,1])
88
+ begin
89
+ hash = CALLSITES[[klass.to_s, id.to_s]] ||= {}
90
+ hash[caller_arr] ||= 0
91
+ hash[caller_arr] += 1
92
+ #puts "#{event} #{file} #{line} #{klass.inspect} " +
93
+ # "#{klass.object_id} #{id} #{eval('self', binding)}"
94
+ rescue Exception
95
+ end
96
+ end
97
+ when 'c-call', 'c-return', 'class'
98
+ return
99
+ end
100
+ if @coverage_hook_activated
101
+ COVER[file] ||= Array.new(SCRIPT_LINES__[file].size, 0)
102
+ COVER[file][line - 1] ||= 0
103
+ COVER[file][line - 1] += 1
104
+ end
105
+ }
106
+ end
107
+
108
+ def self.remove_coverage_hook # :nodoc:
109
+ @coverage_hook_activated = false
110
+ set_trace_func(nil) if !@callsite_hook_activated
111
+ end
112
+
113
+ def self.remove_callsite_hook # :nodoc:
114
+ @callsite_hook_activated = false
115
+ set_trace_func(nil) if !@coverage_hook_activated
116
+ end
117
+
118
+ def self.reset_coverage # :nodoc:
119
+ COVER.replace({})
120
+ end
121
+
122
+ def self.reset_callsite # :nodoc:
123
+ CALLSITES.replace({})
124
+ DEFSITES.replace({})
125
+ end
126
+
127
+ def self.generate_coverage_info # :nodoc:
128
+ Marshal.load(Marshal.dump(COVER))
129
+ end
130
+
131
+ def self.generate_callsite_info # :nodoc:
132
+ [CALLSITES, DEFSITES]
133
+ end
134
+
135
+ def self.format_backtrace_array(backtrace)
136
+ backtrace.map do |line|
137
+ md = /^([^:]*)(?::(\d+)(?::in `(.*)'))?/.match(line)
138
+ raise "Bad backtrace format" unless md
139
+ [nil, md[3] ? md[3].to_sym : nil, md[1], (md[2] || '').to_i]
140
+ end
141
+ end
142
+ end
143
+ end # RCOV__
144
+
145
+ end # Rcov
146
+
147
+ # vi: set sw=2:
@@ -0,0 +1,87 @@
1
+
2
+ require 'rant/rantlib'
3
+
4
+ module Rant # :nodoc:
5
+ module Generators # :nodoc:
6
+ class Rcov # :nodoc:
7
+ def self.rant_gen(app, ch, args, &block)
8
+ if !args || args.empty?
9
+ self.new(app, ch, &block)
10
+ elsif args.size == 1
11
+ name, pre = app.normalize_task_arg(args.first, ch)
12
+ self.new(app, ch, name, pre, &block)
13
+ else
14
+ app.abort_at(ch,
15
+ "Rcov takes only one additional argument, " +
16
+ "which should be like one given to the `task' command.")
17
+ end
18
+ end
19
+
20
+ attr_accessor :verbose
21
+ attr_accessor :libs
22
+ attr_accessor :test_dirs
23
+ attr_accessor :pattern
24
+ attr_accessor :test_files
25
+ attr_accessor :rcov_opts
26
+ # Directory where to put the generated XHTML reports
27
+ attr_accessor :output_dir
28
+
29
+ def initialize(app, cinf, name = :rcov, prerequisites = [], &block)
30
+ @rac = app
31
+ @name = name
32
+ @pre = prerequisites
33
+ #@block = block
34
+ @verbose = nil
35
+ cf = cinf[:file]
36
+ @libs = []
37
+ libdir = File.join(File.dirname(File.expand_path(cf)), 'lib')
38
+ @libs << libdir if test(?d, libdir)
39
+ @rcov_opts = ["--text-report"]
40
+ @test_dirs = []
41
+ @pattern = nil
42
+ @test_files = nil
43
+ yield self if block_given?
44
+ @pattern = "test*.rb" if @pattern.nil? && @test_files.nil?
45
+ @output_dir ||= "coverage"
46
+
47
+ @pre ||= []
48
+ # define the task
49
+ app.task(:__caller__ => cinf, @name => @pre) { |t|
50
+ args = []
51
+ if @libs && !@libs.empty?
52
+ args << "-I#{@libs.join File::PATH_SEPARATOR}"
53
+ end
54
+ if rcov_path = ENV['RCOVPATH']
55
+ args << rcov_path
56
+ else
57
+ args << "-S" << "rcov"
58
+ end
59
+ args.concat rcov_opts
60
+ args << "-o" << @output_dir
61
+ if test(?d, "test")
62
+ @test_dirs << "test"
63
+ elsif test(?d, "tests")
64
+ @test_dirs << "tests"
65
+ end
66
+ args.concat filelist
67
+ app.context.sys.ruby args
68
+ }
69
+ end
70
+
71
+ def filelist
72
+ return @rac.sys[@rac.var['TEST']] if @rac.var['TEST']
73
+ filelist = @test_files || []
74
+ if filelist.empty?
75
+ if @test_dirs && !@test_dirs.empty?
76
+ @test_dirs.each { |dir|
77
+ filelist.concat(@rac.sys[File.join(dir, @pattern)])
78
+ }
79
+ else
80
+ filelist.concat(@rac.sys[@pattern]) if @pattern
81
+ end
82
+ end
83
+ filelist
84
+ end
85
+ end # class Rcov
86
+ end # module Generators
87
+ end # module Rant
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Define a task library for performing code coverage analysis of unit tests
4
+ # using rcov.
5
+
6
+ require 'rake'
7
+ require 'rake/tasklib'
8
+
9
+ module Rcov
10
+
11
+ # Create a task that runs a set of tests through rcov, generating code
12
+ # coverage reports.
13
+ #
14
+ # Example:
15
+ #
16
+ # require 'rcov/rcovtask'
17
+ #
18
+ # Rcov::RcovTask.new do |t|
19
+ # t.libs << "test"
20
+ # t.test_files = FileList['test/test*.rb']
21
+ # t.verbose = true
22
+ # end
23
+ #
24
+ # If rake is invoked with a "TEST=filename" command line option,
25
+ # then the list of test files will be overridden to include only the
26
+ # filename specified on the command line. This provides an easy way
27
+ # to run just one test.
28
+ #
29
+ # If rake is invoked with a "RCOVOPTS=options" command line option,
30
+ # then the given options are passed to rcov.
31
+ #
32
+ # If rake is invoked with a "RCOVPATH=path/to/rcov" command line option,
33
+ # then the given rcov executable will be used; otherwise the one in your
34
+ # PATH will be used.
35
+ #
36
+ # Examples:
37
+ #
38
+ # rake rcov # run tests normally
39
+ # rake rcov TEST=just_one_file.rb # run just one test file.
40
+ # rake rcov RCOVOPTS="-p" # run in profile mode
41
+ # rake rcov RCOVOPTS="-T" # generate text report
42
+ #
43
+ class RcovTask < Rake::TaskLib
44
+
45
+ # Name of test task. (default is :rcov)
46
+ attr_accessor :name
47
+
48
+ # List of directories to added to $LOAD_PATH before running the
49
+ # tests. (default is 'lib')
50
+ attr_accessor :libs
51
+
52
+ # True if verbose test output desired. (default is false)
53
+ attr_accessor :verbose
54
+
55
+ # Request that the tests be run with the warning flag set.
56
+ # E.g. warning=true implies "ruby -w" used to run the tests.
57
+ attr_accessor :warning
58
+
59
+ # Glob pattern to match test files. (default is 'test/test*.rb')
60
+ attr_accessor :pattern
61
+
62
+ # Array of commandline options to pass to ruby when running the rcov loader.
63
+ attr_accessor :ruby_opts
64
+
65
+ # Array of commandline options to pass to rcov. An explicit
66
+ # RCOVOPTS=opts on the command line will override this. (default
67
+ # is <tt>["--text-report"]</tt>)
68
+ attr_accessor :rcov_opts
69
+
70
+ # Output directory for the XHTML report.
71
+ attr_accessor :output_dir
72
+
73
+ # Explicitly define the list of test files to be included in a
74
+ # test. +list+ is expected to be an array of file names (a
75
+ # FileList is acceptable). If both +pattern+ and +test_files+ are
76
+ # used, then the list of test files is the union of the two.
77
+ def test_files=(list)
78
+ @test_files = list
79
+ end
80
+
81
+ # Create a testing task.
82
+ def initialize(name=:rcov)
83
+ @name = name
84
+ @libs = ["lib"]
85
+ @pattern = nil
86
+ @test_files = nil
87
+ @verbose = false
88
+ @warning = false
89
+ @rcov_opts = ["--text-report"]
90
+ @ruby_opts = []
91
+ @output_dir = "coverage"
92
+ yield self if block_given?
93
+ @pattern = 'test/test*.rb' if @pattern.nil? && @test_files.nil?
94
+ define
95
+ end
96
+
97
+ # Create the tasks defined by this task lib.
98
+ def define
99
+ lib_path = @libs.join(File::PATH_SEPARATOR)
100
+ actual_name = Hash === name ? name.keys.first : name
101
+ unless Rake.application.last_comment
102
+ desc "Analyze code coverage with tests" +
103
+ (@name==:rcov ? "" : " for #{actual_name}")
104
+ end
105
+ task @name do
106
+ run_code = ''
107
+ RakeFileUtils.verbose(@verbose) do
108
+ run_code =
109
+ case rcov_path
110
+ when nil, ''
111
+ "-S rcov"
112
+ else %!"#{rcov_path}"!
113
+ end
114
+ ruby_opts = @ruby_opts.clone
115
+ ruby_opts.push( "-I#{lib_path}" )
116
+ ruby_opts.push run_code
117
+ ruby_opts.push( "-w" ) if @warning
118
+ ruby ruby_opts.join(" ") + " " + option_list +
119
+ %[ -o "#{@output_dir}" ] +
120
+ file_list.collect { |fn| %["#{fn}"] }.join(' ')
121
+ end
122
+ end
123
+
124
+ desc "Remove rcov products for #{actual_name}"
125
+ task paste("clobber_", actual_name) do
126
+ rm_r @output_dir rescue nil
127
+ end
128
+
129
+ clobber_task = paste("clobber_", actual_name)
130
+ task :clobber => [clobber_task]
131
+
132
+ task actual_name => clobber_task
133
+ self
134
+ end
135
+
136
+ def rcov_path # :nodoc:
137
+ ENV['RCOVPATH']
138
+ end
139
+
140
+ def option_list # :nodoc:
141
+ ENV['RCOVOPTS'] || @rcov_opts.join(" ") || ""
142
+ end
143
+
144
+ def file_list # :nodoc:
145
+ if ENV['TEST']
146
+ FileList[ ENV['TEST'] ]
147
+ else
148
+ result = []
149
+ result += @test_files.to_a if @test_files
150
+ result += FileList[ @pattern ].to_a if @pattern
151
+ FileList[result]
152
+ end
153
+ end
154
+ end
155
+ end
156
+
@@ -0,0 +1,1236 @@
1
+ # rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
2
+ # See LEGAL and LICENSE for additional licensing information.
3
+
4
+ require 'pathname'
5
+ module Rcov
6
+
7
+ # Try to fix bugs in the REXML shipped with Ruby 1.8.6
8
+ # They affect Mac OSX 10.5.1 users and motivates endless bug reports.
9
+ begin
10
+ require 'rexml/formatters/transitive'
11
+ require 'rexml/formatter/pretty'
12
+ rescue LoadError
13
+ end
14
+
15
+ if RUBY_VERSION == "1.8.6" && defined? REXML::Formatters::Transitive
16
+ class REXML::Document
17
+ remove_method :write rescue nil
18
+ def write( output=$stdout, indent=-1, trans=false, ie_hack=false )
19
+ if xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
20
+ output = Output.new( output, xml_decl.encoding )
21
+ end
22
+ formatter = if indent > -1
23
+ #if trans
24
+ REXML::Formatters::Transitive.new( indent )
25
+ #else
26
+ # REXML::Formatters::Pretty.new( indent, ie_hack )
27
+ #end
28
+ else
29
+ REXML::Formatters::Default.new( ie_hack )
30
+ end
31
+ formatter.write( self, output )
32
+ end
33
+ end
34
+
35
+ class REXML::Formatters::Transitive
36
+ remove_method :write_element rescue nil
37
+ def write_element( node, output )
38
+ output << "<#{node.expanded_name}"
39
+
40
+ node.attributes.each_attribute do |attr|
41
+ output << " "
42
+ attr.write( output )
43
+ end unless node.attributes.empty?
44
+
45
+ if node.children.empty?
46
+ output << "/>"
47
+ else
48
+ output << ">"
49
+ # If compact and all children are text, and if the formatted output
50
+ # is less than the specified width, then try to print everything on
51
+ # one line
52
+ skip = false
53
+ @level += @indentation
54
+ node.children.each { |child|
55
+ write( child, output )
56
+ }
57
+ @level -= @indentation
58
+ output << "</#{node.expanded_name}>"
59
+ end
60
+ output << "\n"
61
+ output << ' '*@level
62
+ end
63
+ end
64
+ end
65
+
66
+ class Formatter # :nodoc:
67
+ require 'pathname'
68
+ ignore_files = [
69
+ /\A#{Regexp.escape(Pathname.new(Config::CONFIG["libdir"]).cleanpath.to_s)}/,
70
+ /\btc_[^.]*.rb/,
71
+ /_test\.rb\z/,
72
+ /\btest\//,
73
+ /\bvendor\//,
74
+ /\A#{Regexp.escape(__FILE__)}\z/]
75
+ DEFAULT_OPTS = {:ignore => ignore_files, :sort => :name, :sort_reverse => false,
76
+ :output_threshold => 101, :dont_ignore => [],
77
+ :callsite_analyzer => nil, :comments_run_by_default => false}
78
+ def initialize(opts = {})
79
+ options = DEFAULT_OPTS.clone.update(opts)
80
+ @files = {}
81
+ @ignore_files = options[:ignore]
82
+ @dont_ignore_files = options[:dont_ignore]
83
+ @sort_criterium = case options[:sort]
84
+ when :loc : lambda{|fname, finfo| finfo.num_code_lines}
85
+ when :coverage : lambda{|fname, finfo| finfo.code_coverage}
86
+ else lambda{|fname, finfo| fname}
87
+ end
88
+ @sort_reverse = options[:sort_reverse]
89
+ @output_threshold = options[:output_threshold]
90
+ @callsite_analyzer = options[:callsite_analyzer]
91
+ @comments_run_by_default = options[:comments_run_by_default]
92
+ @callsite_index = nil
93
+
94
+ @mangle_filename = Hash.new{|h,base|
95
+ h[base] = Pathname.new(base).cleanpath.to_s.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".html"
96
+ }
97
+ end
98
+
99
+ def add_file(filename, lines, coverage, counts)
100
+ old_filename = filename
101
+ filename = normalize_filename(filename)
102
+ SCRIPT_LINES__[filename] = SCRIPT_LINES__[old_filename]
103
+ if @ignore_files.any?{|x| x === filename} &&
104
+ !@dont_ignore_files.any?{|x| x === filename}
105
+ return nil
106
+ end
107
+ if @files[filename]
108
+ @files[filename].merge(lines, coverage, counts)
109
+ else
110
+ @files[filename] = FileStatistics.new(filename, lines, counts,
111
+ @comments_run_by_default)
112
+ end
113
+ end
114
+
115
+ def normalize_filename(filename)
116
+ File.expand_path(filename).gsub(/^#{Regexp.escape(Dir.getwd)}\//, '')
117
+ end
118
+
119
+ def mangle_filename(base)
120
+ @mangle_filename[base]
121
+ end
122
+
123
+ def each_file_pair_sorted(&b)
124
+ return sorted_file_pairs unless block_given?
125
+ sorted_file_pairs.each(&b)
126
+ end
127
+
128
+ def sorted_file_pairs
129
+ pairs = @files.sort_by do |fname, finfo|
130
+ @sort_criterium.call(fname, finfo)
131
+ end.select{|_, finfo| 100 * finfo.code_coverage < @output_threshold}
132
+ @sort_reverse ? pairs.reverse : pairs
133
+ end
134
+
135
+ def total_coverage
136
+ lines = 0
137
+ total = 0.0
138
+ @files.each do |k,f|
139
+ total += f.num_lines * f.total_coverage
140
+ lines += f.num_lines
141
+ end
142
+ return 0 if lines == 0
143
+ total / lines
144
+ end
145
+
146
+ def code_coverage
147
+ lines = 0
148
+ total = 0.0
149
+ @files.each do |k,f|
150
+ total += f.num_code_lines * f.code_coverage
151
+ lines += f.num_code_lines
152
+ end
153
+ return 0 if lines == 0
154
+ total / lines
155
+ end
156
+
157
+ def num_code_lines
158
+ lines = 0
159
+ @files.each{|k, f| lines += f.num_code_lines }
160
+ lines
161
+ end
162
+
163
+ def num_lines
164
+ lines = 0
165
+ @files.each{|k, f| lines += f.num_lines }
166
+ lines
167
+ end
168
+
169
+ private
170
+ def cross_references_for(filename, lineno)
171
+ return nil unless @callsite_analyzer
172
+ @callsite_index ||= build_callsite_index
173
+ @callsite_index[normalize_filename(filename)][lineno]
174
+ end
175
+
176
+ def reverse_cross_references_for(filename, lineno)
177
+ return nil unless @callsite_analyzer
178
+ @callsite_reverse_index ||= build_reverse_callsite_index
179
+ @callsite_reverse_index[normalize_filename(filename)][lineno]
180
+ end
181
+
182
+ def build_callsite_index
183
+ index = Hash.new{|h,k| h[k] = {}}
184
+ @callsite_analyzer.analyzed_classes.each do |classname|
185
+ @callsite_analyzer.analyzed_methods(classname).each do |methname|
186
+ defsite = @callsite_analyzer.defsite(classname, methname)
187
+ index[normalize_filename(defsite.file)][defsite.line] =
188
+ @callsite_analyzer.callsites(classname, methname)
189
+ end
190
+ end
191
+ index
192
+ end
193
+
194
+ def build_reverse_callsite_index
195
+ index = Hash.new{|h,k| h[k] = {}}
196
+ @callsite_analyzer.analyzed_classes.each do |classname|
197
+ @callsite_analyzer.analyzed_methods(classname).each do |methname|
198
+ callsites = @callsite_analyzer.callsites(classname, methname)
199
+ defsite = @callsite_analyzer.defsite(classname, methname)
200
+ callsites.each_pair do |callsite, count|
201
+ next unless callsite.file
202
+ fname = normalize_filename(callsite.file)
203
+ (index[fname][callsite.line] ||= []) << [classname, methname, defsite, count]
204
+ end
205
+ end
206
+ end
207
+ index
208
+ end
209
+
210
+ class XRefHelper < Struct.new(:file, :line, :klass, :mid, :count) # :nodoc:
211
+ end
212
+
213
+ def _get_defsites(ref_blocks, filename, lineno, linetext, label, &format_call_ref)
214
+ if @do_cross_references and
215
+ (rev_xref = reverse_cross_references_for(filename, lineno))
216
+ refs = rev_xref.map do |classname, methodname, defsite, count|
217
+ XRefHelper.new(defsite.file, defsite.line, classname, methodname, count)
218
+ end.sort_by{|r| r.count}.reverse
219
+ ref_blocks << [refs, label, format_call_ref]
220
+ end
221
+ end
222
+
223
+ def _get_callsites(ref_blocks, filename, lineno, linetext, label, &format_called_ref)
224
+ if @do_callsites and
225
+ (refs = cross_references_for(filename, lineno))
226
+ refs = refs.sort_by{|k,count| count}.map do |ref, count|
227
+ XRefHelper.new(ref.file, ref.line, ref.calling_class, ref.calling_method, count)
228
+ end.reverse
229
+ ref_blocks << [refs, label, format_called_ref]
230
+ end
231
+ end
232
+ end
233
+
234
+ class TextSummary < Formatter # :nodoc:
235
+ def execute
236
+ puts summary
237
+ end
238
+
239
+ def summary
240
+ "%.1f%% %d file(s) %d Lines %d LOC" % [code_coverage * 100,
241
+ @files.size, num_lines, num_code_lines]
242
+ end
243
+ end
244
+
245
+ class TextReport < TextSummary # :nodoc:
246
+ def execute
247
+ print_lines
248
+ print_header
249
+ print_lines
250
+ each_file_pair_sorted do |fname, finfo|
251
+ name = fname.size < 52 ? fname : "..." + fname[-48..-1]
252
+ print_info(name, finfo.num_lines, finfo.num_code_lines,
253
+ finfo.code_coverage)
254
+ end
255
+ print_lines
256
+ print_info("Total", num_lines, num_code_lines, code_coverage)
257
+ print_lines
258
+ puts summary
259
+ end
260
+
261
+ def print_info(name, lines, loc, coverage)
262
+ puts "|%-51s | %5d | %5d | %5.1f%% |" % [name, lines, loc, 100 * coverage]
263
+ end
264
+
265
+ def print_lines
266
+ puts "+----------------------------------------------------+-------+-------+--------+"
267
+ end
268
+
269
+ def print_header
270
+ puts "| File | Lines | LOC | COV |"
271
+ end
272
+ end
273
+
274
+ class FullTextReport < Formatter # :nodoc:
275
+ DEFAULT_OPTS = {:textmode => :coverage}
276
+ def initialize(opts = {})
277
+ options = DEFAULT_OPTS.clone.update(opts)
278
+ @textmode = options[:textmode]
279
+ @color = options[:color]
280
+ super(options)
281
+ end
282
+
283
+ def execute
284
+ each_file_pair_sorted do |filename, fileinfo|
285
+ puts "=" * 80
286
+ puts filename
287
+ puts "=" * 80
288
+ lines = SCRIPT_LINES__[filename]
289
+ unless lines
290
+ # try to get the source code from the global code coverage
291
+ # analyzer
292
+ re = /#{Regexp.escape(filename)}\z/
293
+ if $rcov_code_coverage_analyzer and
294
+ (data = $rcov_code_coverage_analyzer.data_matching(re))
295
+ lines = data[0]
296
+ end
297
+ end
298
+ (lines || []).each_with_index do |line, i|
299
+ case @textmode
300
+ when :counts
301
+ puts "%-70s| %6d" % [line.chomp[0,70], fileinfo.counts[i]]
302
+ when :gcc
303
+ puts "%s:%d:%s" % [filename, i+1, line.chomp] unless fileinfo.coverage[i]
304
+ when :coverage
305
+ if @color
306
+ prefix = fileinfo.coverage[i] ? "\e[32;40m" : "\e[31;40m"
307
+ puts "#{prefix}%s\e[37;40m" % line.chomp
308
+ else
309
+ prefix = fileinfo.coverage[i] ? " " : "!! "
310
+ puts "#{prefix}#{line}"
311
+ end
312
+ end
313
+ end
314
+ end
315
+ end
316
+ end
317
+
318
+ class TextCoverageDiff < Formatter # :nodoc:
319
+ FORMAT_VERSION = [0, 1, 0]
320
+ DEFAULT_OPTS = {:textmode => :coverage_diff,
321
+ :coverage_diff_mode => :record,
322
+ :coverage_diff_file => "coverage.info",
323
+ :diff_cmd => "diff", :comments_run_by_default => true}
324
+ def SERIALIZER
325
+ # mfp> this was going to be YAML but I caught it failing at basic
326
+ # round-tripping, turning "\n" into "" and corrupting the data, so
327
+ # it must be Marshal for now
328
+ Marshal
329
+ end
330
+
331
+ def initialize(opts = {})
332
+ options = DEFAULT_OPTS.clone.update(opts)
333
+ @textmode = options[:textmode]
334
+ @color = options[:color]
335
+ @mode = options[:coverage_diff_mode]
336
+ @state_file = options[:coverage_diff_file]
337
+ @diff_cmd = options[:diff_cmd]
338
+ @gcc_output = options[:gcc_output]
339
+ super(options)
340
+ end
341
+
342
+ def execute
343
+ case @mode
344
+ when :record
345
+ record_state
346
+ when :compare
347
+ compare_state
348
+ else
349
+ raise "Unknown TextCoverageDiff mode: #{mode.inspect}."
350
+ end
351
+ end
352
+
353
+ def record_state
354
+ state = {}
355
+ each_file_pair_sorted do |filename, fileinfo|
356
+ state[filename] = {:lines => SCRIPT_LINES__[filename],
357
+ :coverage => fileinfo.coverage.to_a,
358
+ :counts => fileinfo.counts}
359
+ end
360
+ File.open(@state_file, "w") do |f|
361
+ self.SERIALIZER.dump([FORMAT_VERSION, state], f)
362
+ end
363
+ rescue
364
+ $stderr.puts <<-EOF
365
+ Couldn't save coverage data to #{@state_file}.
366
+ EOF
367
+ end # '
368
+
369
+ require 'tempfile'
370
+ def compare_state
371
+ return unless verify_diff_available
372
+ begin
373
+ format, prev_state = File.open(@state_file){|f| self.SERIALIZER.load(f) }
374
+ rescue
375
+ $stderr.puts <<-EOF
376
+ Couldn't load coverage data from #{@state_file}.
377
+ EOF
378
+ return # '
379
+ end
380
+ if !(Array === format) or
381
+ FORMAT_VERSION[0] != format[0] || FORMAT_VERSION[1] < format[1]
382
+ $stderr.puts <<-EOF
383
+ Couldn't load coverage data from #{@state_file}.
384
+ The file is saved in the format #{format.inspect[0..20]}.
385
+ This rcov executable understands #{FORMAT_VERSION.inspect}.
386
+ EOF
387
+ return # '
388
+ end
389
+ each_file_pair_sorted do |filename, fileinfo|
390
+ old_data = Tempfile.new("#{mangle_filename(filename)}-old")
391
+ new_data = Tempfile.new("#{mangle_filename(filename)}-new")
392
+ if prev_state.has_key? filename
393
+ old_code, old_cov = prev_state[filename].values_at(:lines, :coverage)
394
+ old_code.each_with_index do |line, i|
395
+ prefix = old_cov[i] ? " " : "!! "
396
+ old_data.write "#{prefix}#{line}"
397
+ end
398
+ else
399
+ old_data.write ""
400
+ end
401
+ old_data.close
402
+ SCRIPT_LINES__[filename].each_with_index do |line, i|
403
+ prefix = fileinfo.coverage[i] ? " " : "!! "
404
+ new_data.write "#{prefix}#{line}"
405
+ end
406
+ new_data.close
407
+
408
+ diff = `#{@diff_cmd} -u "#{old_data.path}" "#{new_data.path}"`
409
+ new_uncovered_hunks = process_unified_diff(filename, diff)
410
+ old_data.close!
411
+ new_data.close!
412
+ display_hunks(filename, new_uncovered_hunks)
413
+ end
414
+ end
415
+
416
+ def display_hunks(filename, hunks)
417
+ return if hunks.empty?
418
+ puts
419
+ puts "=" * 80
420
+ puts <<EOF
421
+ !!!!! Uncovered code introduced in #{filename}
422
+
423
+ EOF
424
+ hunks.each do |offset, lines|
425
+ if @gcc_output
426
+ lines.each_with_index do |line,i|
427
+ lineno = offset + i
428
+ flag = (/^!! / !~ line) ? "-" : ":"
429
+ prefix = "#{filename}#{flag}#{lineno}#{flag}"
430
+ puts "#{prefix}#{line[3..-1]}"
431
+ end
432
+ elsif @color
433
+ puts "### #{filename}:#{offset}"
434
+ lines.each do |line|
435
+ prefix = (/^!! / !~ line) ? "\e[32;40m" : "\e[31;40m"
436
+ puts "#{prefix}#{line[3..-1].chomp}\e[37;40m"
437
+ end
438
+ else
439
+ puts "### #{filename}:#{offset}"
440
+ puts lines
441
+ end
442
+ end
443
+ end
444
+
445
+ def verify_diff_available
446
+ old_stderr = STDERR.dup
447
+ old_stdout = STDOUT.dup
448
+ # TODO: should use /dev/null or NUL(?), but I don't want to add the
449
+ # win32 check right now
450
+ new_stderr = Tempfile.new("rcov_check_diff")
451
+ STDERR.reopen new_stderr.path
452
+ STDOUT.reopen new_stderr.path
453
+
454
+ retval = system "#{@diff_cmd} --version"
455
+ unless retval
456
+ old_stderr.puts <<EOF
457
+
458
+ The '#{@diff_cmd}' executable seems not to be available.
459
+ You can specify which diff executable should be used with --diff-cmd.
460
+ If your system doesn't have one, you might want to use Diff::LCS's:
461
+ gem install diff-lcs
462
+ and use --diff-cmd=ldiff.
463
+ EOF
464
+ return false
465
+ end
466
+ true
467
+ ensure
468
+ STDOUT.reopen old_stdout
469
+ STDERR.reopen old_stderr
470
+ new_stderr.close!
471
+ end
472
+
473
+ HUNK_HEADER = /@@ -\d+,\d+ \+(\d+),(\d+) @@/
474
+ def process_unified_diff(filename, diff)
475
+ current_hunk = []
476
+ current_hunk_start = 0
477
+ keep_current_hunk = false
478
+ state = :init
479
+ interesting_hunks = []
480
+ diff.each_with_index do |line, i|
481
+ #puts "#{state} %5d #{line}" % i
482
+ case state
483
+ when :init
484
+ if md = HUNK_HEADER.match(line)
485
+ current_hunk = []
486
+ current_hunk_start = md[1].to_i
487
+ state = :body
488
+ end
489
+ when :body
490
+ case line
491
+ when HUNK_HEADER
492
+ new_start = $1.to_i
493
+ if keep_current_hunk
494
+ interesting_hunks << [current_hunk_start, current_hunk]
495
+ end
496
+ current_hunk_start = new_start
497
+ current_hunk = []
498
+ keep_current_hunk = false
499
+ when /^-/
500
+ # ignore
501
+ when /^\+!! /
502
+ keep_current_hunk = true
503
+ current_hunk << line[1..-1]
504
+ else
505
+ current_hunk << line[1..-1]
506
+ end
507
+ end
508
+ end
509
+ if keep_current_hunk
510
+ interesting_hunks << [current_hunk_start, current_hunk]
511
+ end
512
+
513
+ interesting_hunks
514
+ end
515
+ end
516
+
517
+
518
+ class HTMLCoverage < Formatter # :nodoc:
519
+ include XX::XHTML
520
+ include XX::XMLish
521
+ require 'fileutils'
522
+ JAVASCRIPT_PROLOG = <<-EOS
523
+
524
+ // <![CDATA[
525
+ function toggleCode( id ) {
526
+ if ( document.getElementById )
527
+ elem = document.getElementById( id );
528
+ else if ( document.all )
529
+ elem = eval( "document.all." + id );
530
+ else
531
+ return false;
532
+
533
+ elemStyle = elem.style;
534
+
535
+ if ( elemStyle.display != "block" ) {
536
+ elemStyle.display = "block"
537
+ } else {
538
+ elemStyle.display = "none"
539
+ }
540
+
541
+ return true;
542
+ }
543
+
544
+ // Make cross-references hidden by default
545
+ document.writeln( "<style type=\\"text/css\\">span.cross-ref { display: none }</style>" )
546
+ // ]]>
547
+ EOS
548
+
549
+ CSS_PROLOG = <<-EOS
550
+ span.cross-ref-title {
551
+ font-size: 140%;
552
+ }
553
+ span.cross-ref a {
554
+ text-decoration: none;
555
+ }
556
+ span.cross-ref {
557
+ background-color:#f3f7fa;
558
+ border: 1px dashed #333;
559
+ margin: 1em;
560
+ padding: 0.5em;
561
+ overflow: hidden;
562
+ }
563
+ a.crossref-toggle {
564
+ text-decoration: none;
565
+ }
566
+ span.marked0 {
567
+ background-color: rgb(185, 210, 200);
568
+ display: block;
569
+ }
570
+ span.marked1 {
571
+ background-color: rgb(190, 215, 205);
572
+ display: block;
573
+ }
574
+ span.inferred0 {
575
+ background-color: rgb(175, 200, 200);
576
+ display: block;
577
+ }
578
+ span.inferred1 {
579
+ background-color: rgb(180, 205, 205);
580
+ display: block;
581
+ }
582
+ span.uncovered0 {
583
+ background-color: rgb(225, 110, 110);
584
+ display: block;
585
+ }
586
+ span.uncovered1 {
587
+ background-color: rgb(235, 120, 120);
588
+ display: block;
589
+ }
590
+ span.overview {
591
+ border-bottom: 8px solid black;
592
+ }
593
+ div.overview {
594
+ border-bottom: 8px solid black;
595
+ }
596
+ body {
597
+ font-family: verdana, arial, helvetica;
598
+ }
599
+
600
+ div.footer {
601
+ font-size: 68%;
602
+ margin-top: 1.5em;
603
+ }
604
+
605
+ h1, h2, h3, h4, h5, h6 {
606
+ margin-bottom: 0.5em;
607
+ }
608
+
609
+ h5 {
610
+ margin-top: 0.5em;
611
+ }
612
+
613
+ .hidden {
614
+ display: none;
615
+ }
616
+
617
+ div.separator {
618
+ height: 10px;
619
+ }
620
+ /* Commented out for better readability, esp. on IE */
621
+ /*
622
+ table tr td, table tr th {
623
+ font-size: 68%;
624
+ }
625
+
626
+ td.value table tr td {
627
+ font-size: 11px;
628
+ }
629
+ */
630
+
631
+ table.percent_graph {
632
+ height: 12px;
633
+ border: #808080 1px solid;
634
+ empty-cells: show;
635
+ }
636
+
637
+ table.percent_graph td.covered {
638
+ height: 10px;
639
+ background: #00f000;
640
+ }
641
+
642
+ table.percent_graph td.uncovered {
643
+ height: 10px;
644
+ background: #e00000;
645
+ }
646
+
647
+ table.percent_graph td.NA {
648
+ height: 10px;
649
+ background: #eaeaea;
650
+ }
651
+
652
+ table.report {
653
+ border-collapse: collapse;
654
+ width: 100%;
655
+ }
656
+
657
+ table.report td.heading {
658
+ background: #dcecff;
659
+ border: #d0d0d0 1px solid;
660
+ font-weight: bold;
661
+ text-align: center;
662
+ }
663
+
664
+ table.report td.heading:hover {
665
+ background: #c0ffc0;
666
+ }
667
+
668
+ table.report td.text {
669
+ border: #d0d0d0 1px solid;
670
+ }
671
+
672
+ table.report td.value,
673
+ table.report td.lines_total,
674
+ table.report td.lines_code {
675
+ text-align: right;
676
+ border: #d0d0d0 1px solid;
677
+ }
678
+ table.report tr.light {
679
+ background-color: rgb(240, 240, 245);
680
+ }
681
+ table.report tr.dark {
682
+ background-color: rgb(230, 230, 235);
683
+ }
684
+ EOS
685
+
686
+ DEFAULT_OPTS = {:color => false, :fsr => 30, :destdir => "coverage",
687
+ :callsites => false, :cross_references => false,
688
+ :validator_links => true, :charset => nil
689
+ }
690
+ def initialize(opts = {})
691
+ options = DEFAULT_OPTS.clone.update(opts)
692
+ super(options)
693
+ @dest = options[:destdir]
694
+ @color = options[:color]
695
+ @fsr = options[:fsr]
696
+ @do_callsites = options[:callsites]
697
+ @do_cross_references = options[:cross_references]
698
+ @span_class_index = 0
699
+ @show_validator_links = options[:validator_links]
700
+ @charset = options[:charset]
701
+ end
702
+
703
+ def execute
704
+ return if @files.empty?
705
+ FileUtils.mkdir_p @dest
706
+ create_index(File.join(@dest, "index.html"))
707
+ each_file_pair_sorted do |filename, fileinfo|
708
+ create_file(File.join(@dest, mangle_filename(filename)), fileinfo)
709
+ end
710
+ end
711
+
712
+ private
713
+
714
+ def blurb
715
+ xmlish_ {
716
+ p_ {
717
+ t_{ "Generated using the " }
718
+ a_(:href => "http://eigenclass.org/hiki.rb?rcov") {
719
+ t_{ "rcov code coverage analysis tool for Ruby" }
720
+ }
721
+ t_{ " version #{Rcov::VERSION}." }
722
+ }
723
+ }.pretty
724
+ end
725
+
726
+ def output_color_table?
727
+ true
728
+ end
729
+
730
+ def default_color
731
+ "rgb(240, 240, 245)"
732
+ end
733
+
734
+ def default_title
735
+ "C0 code coverage information"
736
+ end
737
+
738
+ def format_overview(*file_infos)
739
+ table_text = xmlish_ {
740
+ table_(:class => "report") {
741
+ thead_ {
742
+ tr_ {
743
+ ["Name", "Total lines", "Lines of code", "Total coverage",
744
+ "Code coverage"].each do |heading|
745
+ td_(:class => "heading") { heading }
746
+ end
747
+ }
748
+ }
749
+ tbody_ {
750
+ color_class_index = 1
751
+ color_classes = %w[light dark]
752
+ file_infos.each do |f|
753
+ color_class_index += 1
754
+ color_class_index %= color_classes.size
755
+ tr_(:class => color_classes[color_class_index]) {
756
+ td_ {
757
+ case f.name
758
+ when "TOTAL":
759
+ t_ { "TOTAL" }
760
+ else
761
+ a_(:href => mangle_filename(f.name)){ t_ { f.name } }
762
+ end
763
+ }
764
+ [[f.num_lines, "lines_total"],
765
+ [f.num_code_lines, "lines_code"]].each do |value, css_class|
766
+ td_(:class => css_class) { tt_{ value } }
767
+ end
768
+ [[f.total_coverage, "coverage_total"],
769
+ [f.code_coverage, "coverage_code"]].each do |value, css_class|
770
+ value *= 100
771
+ td_ {
772
+ table_(:cellpadding => "0", :cellspacing => "0", :align => "right") {
773
+ tr_ {
774
+ td_ {
775
+ tt_(:class => css_class) { "%3.1f%%" % value }
776
+ x_ "&nbsp;"
777
+ }
778
+ ivalue = value.round
779
+ td_ {
780
+ table_(:class => "percent_graph", :cellpadding => "0",
781
+ :cellspacing => "0", :width => "100") {
782
+ tr_ {
783
+ td_(:class => "covered", :width => ivalue.to_s)
784
+ td_(:class => "uncovered", :width => (100-ivalue).to_s)
785
+ }
786
+ }
787
+ }
788
+ }
789
+ }
790
+ }
791
+ end
792
+ }
793
+ end
794
+ }
795
+ }
796
+ }
797
+ table_text.pretty
798
+ end
799
+
800
+ class SummaryFileInfo # :nodoc:
801
+ def initialize(obj); @o = obj end
802
+ %w[num_lines num_code_lines code_coverage total_coverage].each do |m|
803
+ define_method(m){ @o.send(m) }
804
+ end
805
+ def name; "TOTAL" end
806
+ end
807
+
808
+ def create_index(destname)
809
+ files = [SummaryFileInfo.new(self)] + each_file_pair_sorted.map{|k,v| v}
810
+ title = default_title
811
+ output = xhtml_ { html_ {
812
+ head_ {
813
+ if @charset
814
+ meta_("http-equiv".to_sym => "Content-Type",
815
+ :content => "text/html;charset=#{@charset}")
816
+ end
817
+ title_{ title }
818
+ style_(:type => "text/css") { t_{ "body { background-color: #{default_color}; }" } }
819
+ style_(:type => "text/css") { CSS_PROLOG }
820
+ script_(:type => "text/javascript") { h_{ JAVASCRIPT_PROLOG } }
821
+ }
822
+ body_ {
823
+ h3_{
824
+ t_{ title }
825
+ }
826
+ p_ {
827
+ t_{ "Generated on #{Time.new.to_s} with " }
828
+ a_(:href => Rcov::UPSTREAM_URL){ "rcov #{Rcov::VERSION}" }
829
+ }
830
+ p_ { "Threshold: #{@output_threshold}%" } if @output_threshold != 101
831
+ hr_
832
+ x_{ format_overview(*files) }
833
+ hr_
834
+ x_{ blurb }
835
+
836
+ if @show_validator_links
837
+ p_ {
838
+ a_(:href => "http://validator.w3.org/check/referer") {
839
+ img_(:src => "http://www.w3.org/Icons/valid-xhtml11",
840
+ :alt => "Valid XHTML 1.1!", :height => "31", :width => "88")
841
+ }
842
+ a_(:href => "http://jigsaw.w3.org/css-validator/check/referer") {
843
+ img_(:style => "border:0;width:88px;height:31px",
844
+ :src => "http://jigsaw.w3.org/css-validator/images/vcss",
845
+ :alt => "Valid CSS!")
846
+ }
847
+ }
848
+ end
849
+ }
850
+ } }
851
+ lines = output.pretty.to_a
852
+ lines.unshift lines.pop if /DOCTYPE/ =~ lines[-1]
853
+ File.open(destname, "w") do |f|
854
+ f.puts lines
855
+ end
856
+ end
857
+
858
+ def format_lines(file)
859
+ result = ""
860
+ last = nil
861
+ end_of_span = ""
862
+ format_line = "%#{file.num_lines.to_s.size}d"
863
+ file.num_lines.times do |i|
864
+ line = file.lines[i].chomp
865
+ marked = file.coverage[i]
866
+ count = file.counts[i]
867
+ spanclass = span_class(file, marked, count)
868
+ if spanclass != last
869
+ result += end_of_span
870
+ case spanclass
871
+ when nil
872
+ end_of_span = ""
873
+ else
874
+ result += %[<span class="#{spanclass}">]
875
+ end_of_span = "</span>"
876
+ end
877
+ end
878
+ result += %[<a name="line#{i+1}"></a>] + (format_line % (i+1)) +
879
+ " " + create_cross_refs(file.name, i+1, CGI.escapeHTML(line)) + "\n"
880
+ last = spanclass
881
+ end
882
+ result += end_of_span
883
+ "<pre>#{result}</pre>"
884
+ end
885
+
886
+ def create_cross_refs(filename, lineno, linetext)
887
+ return linetext unless @callsite_analyzer && @do_callsites
888
+ ref_blocks = []
889
+ _get_defsites(ref_blocks, filename, lineno, "Calls", linetext) do |ref|
890
+ if ref.file
891
+ where = "at #{normalize_filename(ref.file)}:#{ref.line}"
892
+ else
893
+ where = "(C extension/core)"
894
+ end
895
+ CGI.escapeHTML("%7d %s" %
896
+ [ref.count, "#{ref.klass}##{ref.mid} " + where])
897
+ end
898
+ _get_callsites(ref_blocks, filename, lineno, "Called by", linetext) do |ref|
899
+ r = "%7d %s" % [ref.count,
900
+ "#{normalize_filename(ref.file||'C code')}:#{ref.line} " +
901
+ "in '#{ref.klass}##{ref.mid}'"]
902
+ CGI.escapeHTML(r)
903
+ end
904
+
905
+ create_cross_reference_block(linetext, ref_blocks)
906
+ end
907
+
908
+ def create_cross_reference_block(linetext, ref_blocks)
909
+ return linetext if ref_blocks.empty?
910
+ ret = ""
911
+ @cross_ref_idx ||= 0
912
+ @known_files ||= sorted_file_pairs.map{|fname, finfo| normalize_filename(fname)}
913
+ ret << %[<a class="crossref-toggle" href="#" onclick="toggleCode('XREF-#{@cross_ref_idx+=1}'); return false;">#{linetext}</a>]
914
+ ret << %[<span class="cross-ref" id="XREF-#{@cross_ref_idx}">]
915
+ ret << "\n"
916
+ ref_blocks.each do |refs, toplabel, label_proc|
917
+ unless !toplabel || toplabel.empty?
918
+ ret << %!<span class="cross-ref-title">#{toplabel}</span>\n!
919
+ end
920
+ refs.each do |dst|
921
+ dstfile = normalize_filename(dst.file) if dst.file
922
+ dstline = dst.line
923
+ label = label_proc.call(dst)
924
+ if dst.file && @known_files.include?(dstfile)
925
+ ret << %[<a href="#{mangle_filename(dstfile)}#line#{dstline}">#{label}</a>]
926
+ else
927
+ ret << label
928
+ end
929
+ ret << "\n"
930
+ end
931
+ end
932
+ ret << "</span>"
933
+ end
934
+
935
+ def span_class(sourceinfo, marked, count)
936
+ @span_class_index ^= 1
937
+ case marked
938
+ when true
939
+ "marked#{@span_class_index}"
940
+ when :inferred
941
+ "inferred#{@span_class_index}"
942
+ else
943
+ "uncovered#{@span_class_index}"
944
+ end
945
+ end
946
+
947
+ def create_file(destfile, fileinfo)
948
+ #$stderr.puts "Generating #{destfile.inspect}"
949
+ body = format_overview(fileinfo) + format_lines(fileinfo)
950
+ title = fileinfo.name + " - #{default_title}"
951
+ do_ctable = output_color_table?
952
+ output = xhtml_ { html_ {
953
+ head_ {
954
+ if @charset
955
+ meta_("http-equiv".to_sym => "Content-Type",
956
+ :content => "text/html;charset=#{@charset}")
957
+ end
958
+ title_{ title }
959
+ style_(:type => "text/css") { t_{ "body { background-color: #{default_color}; }" } }
960
+ style_(:type => "text/css") { CSS_PROLOG }
961
+ script_(:type => "text/javascript") { h_ { JAVASCRIPT_PROLOG } }
962
+ style_(:type => "text/css") { h_ { colorscale } }
963
+ }
964
+ body_ {
965
+ h3_{ t_{ default_title } }
966
+ p_ {
967
+ t_{ "Generated on #{Time.new.to_s} with " }
968
+ a_(:href => Rcov::UPSTREAM_URL){ "rcov #{Rcov::VERSION}" }
969
+ }
970
+ hr_
971
+ if do_ctable
972
+ # this kludge needed to ensure .pretty doesn't mangle it
973
+ x_ { <<EOS
974
+ <pre><span class='marked0'>Code reported as executed by Ruby looks like this...
975
+ </span><span class='marked1'>and this: this line is also marked as covered.
976
+ </span><span class='inferred0'>Lines considered as run by rcov, but not reported by Ruby, look like this,
977
+ </span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).
978
+ </span><span class='uncovered0'>Finally, here&apos;s a line marked as not executed.
979
+ </span></pre>
980
+ EOS
981
+ }
982
+ end
983
+ x_{ body }
984
+ hr_
985
+ x_ { blurb }
986
+
987
+ if @show_validator_links
988
+ p_ {
989
+ a_(:href => "http://validator.w3.org/check/referer") {
990
+ img_(:src => "http://www.w3.org/Icons/valid-xhtml10",
991
+ :alt => "Valid XHTML 1.0!", :height => "31", :width => "88")
992
+ }
993
+ a_(:href => "http://jigsaw.w3.org/css-validator/check/referer") {
994
+ img_(:style => "border:0;width:88px;height:31px",
995
+ :src => "http://jigsaw.w3.org/css-validator/images/vcss",
996
+ :alt => "Valid CSS!")
997
+ }
998
+ }
999
+ end
1000
+ }
1001
+ } }
1002
+ # .pretty needed to make sure DOCTYPE is in a separate line
1003
+ lines = output.pretty.to_a
1004
+ lines.unshift lines.pop if /DOCTYPE/ =~ lines[-1]
1005
+ File.open(destfile, "w") do |f|
1006
+ f.puts lines
1007
+ end
1008
+ end
1009
+
1010
+ def colorscale
1011
+ colorscalebase =<<EOF
1012
+ span.run%d {
1013
+ background-color: rgb(%d, %d, %d);
1014
+ display: block;
1015
+ }
1016
+ EOF
1017
+ cscale = ""
1018
+ 101.times do |i|
1019
+ if @color
1020
+ r, g, b = hsv2rgb(220-(2.2*i).to_i, 0.3, 1)
1021
+ r = (r * 255).to_i
1022
+ g = (g * 255).to_i
1023
+ b = (b * 255).to_i
1024
+ else
1025
+ r = g = b = 255 - i
1026
+ end
1027
+ cscale << colorscalebase % [i, r, g, b]
1028
+ end
1029
+ cscale
1030
+ end
1031
+
1032
+ # thanks to kig @ #ruby-lang for this one
1033
+ def hsv2rgb(h,s,v)
1034
+ return [v,v,v] if s == 0
1035
+ h = h/60.0
1036
+ i = h.floor
1037
+ f = h-i
1038
+ p = v * (1-s)
1039
+ q = v * (1-s*f)
1040
+ t = v * (1-s*(1-f))
1041
+ case i
1042
+ when 0
1043
+ r = v
1044
+ g = t
1045
+ b = p
1046
+ when 1
1047
+ r = q
1048
+ g = v
1049
+ b = p
1050
+ when 2
1051
+ r = p
1052
+ g = v
1053
+ b = t
1054
+ when 3
1055
+ r = p
1056
+ g = q
1057
+ b = v
1058
+ when 4
1059
+ r = t
1060
+ g = p
1061
+ b = v
1062
+ when 5
1063
+ r = v
1064
+ g = p
1065
+ b = q
1066
+ end
1067
+ [r,g,b]
1068
+ end
1069
+ end
1070
+
1071
+ class HTMLProfiling < HTMLCoverage # :nodoc:
1072
+
1073
+ DEFAULT_OPTS = {:destdir => "profiling"}
1074
+ def initialize(opts = {})
1075
+ options = DEFAULT_OPTS.clone.update(opts)
1076
+ super(options)
1077
+ @max_cache = {}
1078
+ @median_cache = {}
1079
+ end
1080
+
1081
+ def default_title
1082
+ "Bogo-profile information"
1083
+ end
1084
+
1085
+ def default_color
1086
+ if @color
1087
+ "rgb(179,205,255)"
1088
+ else
1089
+ "rgb(255, 255, 255)"
1090
+ end
1091
+ end
1092
+
1093
+ def output_color_table?
1094
+ false
1095
+ end
1096
+
1097
+ def span_class(sourceinfo, marked, count)
1098
+ full_scale_range = @fsr # dB
1099
+ nz_count = sourceinfo.counts.select{|x| x && x != 0}
1100
+ nz_count << 1 # avoid div by 0
1101
+ max = @max_cache[sourceinfo] ||= nz_count.max
1102
+ #avg = @median_cache[sourceinfo] ||= 1.0 *
1103
+ # nz_count.inject{|a,b| a+b} / nz_count.size
1104
+ median = @median_cache[sourceinfo] ||= 1.0 * nz_count.sort[nz_count.size/2]
1105
+ max ||= 2
1106
+ max = 2 if max == 1
1107
+ if marked == true
1108
+ count = 1 if !count || count == 0
1109
+ idx = 50 + 1.0 * (500/full_scale_range) * Math.log(count/median) /
1110
+ Math.log(10)
1111
+ idx = idx.to_i
1112
+ idx = 0 if idx < 0
1113
+ idx = 100 if idx > 100
1114
+ "run#{idx}"
1115
+ else
1116
+ nil
1117
+ end
1118
+ end
1119
+ end
1120
+
1121
+ class RubyAnnotation < Formatter # :nodoc:
1122
+ DEFAULT_OPTS = { :destdir => "coverage" }
1123
+ def initialize(opts = {})
1124
+ options = DEFAULT_OPTS.clone.update(opts)
1125
+ super(options)
1126
+ @dest = options[:destdir]
1127
+ @do_callsites = true
1128
+ @do_cross_references = true
1129
+
1130
+ @mangle_filename = Hash.new{|h,base|
1131
+ h[base] = Pathname.new(base).cleanpath.to_s.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".rb"
1132
+ }
1133
+ end
1134
+
1135
+ def execute
1136
+ return if @files.empty?
1137
+ FileUtils.mkdir_p @dest
1138
+ each_file_pair_sorted do |filename, fileinfo|
1139
+ create_file(File.join(@dest, mangle_filename(filename)), fileinfo)
1140
+ end
1141
+ end
1142
+
1143
+ private
1144
+
1145
+ def format_lines(file)
1146
+ result = ""
1147
+ format_line = "%#{file.num_lines.to_s.size}d"
1148
+ file.num_lines.times do |i|
1149
+ line = file.lines[i].chomp
1150
+ marked = file.coverage[i]
1151
+ count = file.counts[i]
1152
+ result << create_cross_refs(file.name, i+1, line, marked) + "\n"
1153
+ end
1154
+ result
1155
+ end
1156
+
1157
+ def create_cross_refs(filename, lineno, linetext, marked)
1158
+ return linetext unless @callsite_analyzer && @do_callsites
1159
+ ref_blocks = []
1160
+ _get_defsites(ref_blocks, filename, lineno, linetext, ">>") do |ref|
1161
+ if ref.file
1162
+ ref.file.sub!(%r!^./!, '')
1163
+ where = "at #{mangle_filename(ref.file)}:#{ref.line}"
1164
+ else
1165
+ where = "(C extension/core)"
1166
+ end
1167
+ "#{ref.klass}##{ref.mid} " + where + ""
1168
+ end
1169
+ _get_callsites(ref_blocks, filename, lineno, linetext, "<<") do |ref| # "
1170
+ ref.file.sub!(%r!^./!, '')
1171
+ "#{mangle_filename(ref.file||'C code')}:#{ref.line} " +
1172
+ "in #{ref.klass}##{ref.mid}"
1173
+ end
1174
+
1175
+ create_cross_reference_block(linetext, ref_blocks, marked)
1176
+ end
1177
+
1178
+ def create_cross_reference_block(linetext, ref_blocks, marked)
1179
+ codelen = 75
1180
+ if ref_blocks.empty?
1181
+ if marked
1182
+ return "%-#{codelen}s #o" % linetext
1183
+ else
1184
+ return linetext
1185
+ end
1186
+ end
1187
+ ret = ""
1188
+ @cross_ref_idx ||= 0
1189
+ @known_files ||= sorted_file_pairs.map{|fname, finfo| normalize_filename(fname)}
1190
+ ret << "%-#{codelen}s # " % linetext
1191
+ ref_blocks.each do |refs, toplabel, label_proc|
1192
+ unless !toplabel || toplabel.empty?
1193
+ ret << toplabel << " "
1194
+ end
1195
+ refs.each do |dst|
1196
+ dstfile = normalize_filename(dst.file) if dst.file
1197
+ dstline = dst.line
1198
+ label = label_proc.call(dst)
1199
+ if dst.file && @known_files.include?(dstfile)
1200
+ ret << "[[" << label << "]], "
1201
+ else
1202
+ ret << label << ", "
1203
+ end
1204
+ end
1205
+ end
1206
+
1207
+ ret
1208
+ end
1209
+
1210
+ def create_file(destfile, fileinfo)
1211
+ #$stderr.puts "Generating #{destfile.inspect}"
1212
+ body = format_lines(fileinfo)
1213
+ File.open(destfile, "w") do |f|
1214
+ f.puts body
1215
+ f.puts footer(fileinfo)
1216
+ end
1217
+ end
1218
+
1219
+ def footer(fileinfo)
1220
+ s = "# Total lines : %d\n" % fileinfo.num_lines
1221
+ s << "# Lines of code : %d\n" % fileinfo.num_code_lines
1222
+ s << "# Total coverage : %3.1f%%\n" % [ fileinfo.total_coverage*100 ]
1223
+ s << "# Code coverage : %3.1f%%\n\n" % [ fileinfo.code_coverage*100 ]
1224
+ # prevents false positives on Emacs
1225
+ s << "# Local " "Variables:\n" "# mode: " "rcov-xref\n" "# End:\n"
1226
+ end
1227
+ end
1228
+
1229
+
1230
+ end # Rcov
1231
+
1232
+ # vi: set sw=4:
1233
+ # Here is Emacs setting. DO NOT REMOVE!
1234
+ # Local Variables:
1235
+ # ruby-indent-level: 4
1236
+ # End: