tap 0.9.1 → 0.10.0

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 (244) hide show
  1. data/History +37 -30
  2. data/MIT-LICENSE +1 -1
  3. data/README +92 -44
  4. data/bin/tap +62 -75
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +6 -45
  13. data/lib/tap/app.rb +126 -500
  14. data/lib/tap/constants.rb +2 -29
  15. data/lib/tap/env.rb +555 -250
  16. data/lib/tap/file_task.rb +60 -103
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +16 -12
  21. data/lib/tap/generator/generators/command/templates/command.erb +13 -19
  22. data/lib/tap/generator/generators/config/config_generator.rb +18 -27
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -11
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -2
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +24 -31
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +18 -22
  30. data/lib/tap/generator/generators/root/root_generator.rb +45 -31
  31. data/lib/tap/generator/generators/root/templates/Rakefile +64 -41
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +21 -28
  38. data/lib/tap/generator/generators/task/templates/task.erb +13 -23
  39. data/lib/tap/generator/generators/task/templates/test.erb +15 -18
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +0 -0
  42. data/lib/tap/patches/rake/testtask.rb +0 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +0 -0
  45. data/lib/tap/root.rb +260 -21
  46. data/lib/tap/support/aggregator.rb +11 -11
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +20 -18
  49. data/lib/tap/support/batchable.rb +21 -10
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +154 -239
  52. data/lib/tap/support/command_line.rb +97 -102
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +86 -65
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +30 -17
  61. data/lib/tap/support/executable_queue.rb +0 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +0 -0
  68. data/lib/tap/support/shell_utils.rb +33 -9
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +339 -134
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +409 -76
  75. data/lib/tap/support/versions.rb +5 -3
  76. data/lib/tap/task.rb +78 -174
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +3 -3
  80. data/lib/tap/test/env_vars.rb +2 -2
  81. data/lib/tap/test/file_methods.rb +19 -20
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +1 -1
  84. data/lib/tap/test/tap_methods.rb +28 -62
  85. data/lib/tap/workflow.rb +22 -39
  86. metadata +48 -179
  87. data/Basic Overview +0 -151
  88. data/Command Reference +0 -99
  89. data/Rakefile +0 -127
  90. data/Tutorial +0 -287
  91. data/lib/tap/cmd/console.rb +0 -31
  92. data/lib/tap/cmd/destroy.rb +0 -20
  93. data/lib/tap/cmd/generate.rb +0 -20
  94. data/lib/tap/cmd/run.rb +0 -151
  95. data/lib/tap/dump.rb +0 -57
  96. data/lib/tap/generator.rb +0 -91
  97. data/lib/tap/generator/generators/command/USAGE +0 -6
  98. data/lib/tap/generator/generators/config/USAGE +0 -21
  99. data/lib/tap/generator/generators/config/templates/config.erb +0 -1
  100. data/lib/tap/generator/generators/file_task/USAGE +0 -3
  101. data/lib/tap/generator/generators/file_task/templates/file.yml +0 -3
  102. data/lib/tap/generator/generators/generator/USAGE +0 -0
  103. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -21
  104. data/lib/tap/generator/generators/generator/templates/generator.erb +0 -32
  105. data/lib/tap/generator/generators/generator/templates/usage.erb +0 -1
  106. data/lib/tap/generator/generators/root/USAGE +0 -0
  107. data/lib/tap/generator/generators/root/templates/ReadMe.txt +0 -0
  108. data/lib/tap/generator/generators/root/templates/tap.yml +0 -80
  109. data/lib/tap/generator/generators/task/USAGE +0 -3
  110. data/lib/tap/generator/generators/workflow/USAGE +0 -0
  111. data/lib/tap/generator/generators/workflow/templates/task.erb +0 -16
  112. data/lib/tap/generator/generators/workflow/templates/test.erb +0 -7
  113. data/lib/tap/generator/generators/workflow/workflow_generator.rb +0 -6
  114. data/lib/tap/generator/options.rb +0 -26
  115. data/lib/tap/generator/usage.rb +0 -26
  116. data/lib/tap/support/batchable_methods.rb +0 -34
  117. data/lib/tap/support/command_line_methods.rb +0 -76
  118. data/lib/tap/support/configurable_methods.rb +0 -224
  119. data/lib/tap/support/logger.rb +0 -88
  120. data/lib/tap/support/rake.rb +0 -43
  121. data/lib/tap/support/tdoc/config_attr.rb +0 -362
  122. data/test/app/config/another/task.yml +0 -1
  123. data/test/app/config/batch.yml +0 -2
  124. data/test/app/config/empty.yml +0 -0
  125. data/test/app/config/erb.yml +0 -2
  126. data/test/app/config/some/task.yml +0 -1
  127. data/test/app/config/template.yml +0 -2
  128. data/test/app/config/version-0.1.yml +0 -1
  129. data/test/app/config/version.yml +0 -1
  130. data/test/app/lib/app_test_task.rb +0 -3
  131. data/test/app_test.rb +0 -1849
  132. data/test/env/test_configure/recurse_a.yml +0 -2
  133. data/test/env/test_configure/recurse_b.yml +0 -2
  134. data/test/env/test_configure/tap.yml +0 -23
  135. data/test/env/test_load_env_config/dir/tap.yml +0 -3
  136. data/test/env/test_load_env_config/recurse_a.yml +0 -2
  137. data/test/env/test_load_env_config/recurse_b.yml +0 -2
  138. data/test/env/test_load_env_config/tap.yml +0 -3
  139. data/test/env_test.rb +0 -198
  140. data/test/file_task/config/batch.yml +0 -2
  141. data/test/file_task/config/configured.yml +0 -1
  142. data/test/file_task/old_file_one.txt +0 -0
  143. data/test/file_task/old_file_two.txt +0 -0
  144. data/test/file_task_test.rb +0 -1291
  145. data/test/root/alt_lib/alt_module.rb +0 -4
  146. data/test/root/file.txt +0 -0
  147. data/test/root/glob/one.txt +0 -0
  148. data/test/root/glob/two.txt +0 -0
  149. data/test/root/lib/absolute_alt_filepath.rb +0 -2
  150. data/test/root/lib/alternative_filepath.rb +0 -2
  151. data/test/root/lib/another_module.rb +0 -2
  152. data/test/root/lib/nested/some_module.rb +0 -4
  153. data/test/root/lib/no_module_included.rb +0 -0
  154. data/test/root/lib/some/module.rb +0 -4
  155. data/test/root/lib/some_class.rb +0 -2
  156. data/test/root/lib/some_module.rb +0 -3
  157. data/test/root/load_path/load_path_module.rb +0 -2
  158. data/test/root/load_path/skip_module.rb +0 -2
  159. data/test/root/mtime/older.txt +0 -0
  160. data/test/root/unload/full_path.rb +0 -2
  161. data/test/root/unload/loaded_by_nested.rb +0 -2
  162. data/test/root/unload/nested/nested_load.rb +0 -6
  163. data/test/root/unload/nested/nested_with_ext.rb +0 -4
  164. data/test/root/unload/nested/relative_path.rb +0 -4
  165. data/test/root/unload/older.rb +0 -2
  166. data/test/root/unload/unload_base.rb +0 -9
  167. data/test/root/versions/another.yml +0 -0
  168. data/test/root/versions/file-0.1.2.yml +0 -0
  169. data/test/root/versions/file-0.1.yml +0 -0
  170. data/test/root/versions/file.yml +0 -0
  171. data/test/root_test.rb +0 -718
  172. data/test/support/aggregator_test.rb +0 -99
  173. data/test/support/audit_test.rb +0 -445
  174. data/test/support/batchable_test.rb +0 -74
  175. data/test/support/class_configuration_test.rb +0 -331
  176. data/test/support/command_line_test.rb +0 -58
  177. data/test/support/configurable/config/configured.yml +0 -2
  178. data/test/support/configurable_test.rb +0 -295
  179. data/test/support/executable_queue_test.rb +0 -103
  180. data/test/support/executable_test.rb +0 -38
  181. data/test/support/logger_test.rb +0 -31
  182. data/test/support/rake_test.rb +0 -37
  183. data/test/support/shell_utils_test.rb +0 -24
  184. data/test/support/tdoc_test.rb +0 -370
  185. data/test/support/validation_test.rb +0 -54
  186. data/test/support/versions_test.rb +0 -103
  187. data/test/tap_test_helper.rb +0 -57
  188. data/test/tap_test_suite.rb +0 -7
  189. data/test/task/config/batch.yml +0 -2
  190. data/test/task/config/batched.yml +0 -2
  191. data/test/task/config/configured.yml +0 -1
  192. data/test/task/config/example.yml +0 -1
  193. data/test/task_base_test.rb +0 -24
  194. data/test/task_syntax_test.rb +0 -300
  195. data/test/task_test.rb +0 -320
  196. data/test/test/env_vars_test.rb +0 -48
  197. data/test/test/file_methods/test_assert_files/expected/one.txt +0 -1
  198. data/test/test/file_methods/test_assert_files/expected/two.txt +0 -1
  199. data/test/test/file_methods/test_assert_files/input/one.txt +0 -1
  200. data/test/test/file_methods/test_assert_files/input/two.txt +0 -1
  201. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/one.txt +0 -1
  202. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/two.txt +0 -1
  203. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +0 -1
  204. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/two.txt +0 -1
  205. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +0 -1
  206. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +0 -1
  207. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/expected/one.txt +0 -1
  208. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +0 -1
  209. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +0 -1
  210. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +0 -1
  211. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +0 -1
  212. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +0 -1
  213. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +0 -1
  214. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +0 -1
  215. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +0 -1
  216. data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
  217. data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
  218. data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
  219. data/test/test/file_methods_doc/test_sub/expected/one.txt +0 -1
  220. data/test/test/file_methods_doc/test_sub/expected/two.txt +0 -1
  221. data/test/test/file_methods_doc/test_sub/input/one.txt +0 -1
  222. data/test/test/file_methods_doc/test_sub/input/two.txt +0 -1
  223. data/test/test/file_methods_doc_test.rb +0 -29
  224. data/test/test/file_methods_test.rb +0 -275
  225. data/test/test/subset_methods_test.rb +0 -171
  226. data/test/test/tap_methods/test_assert_files/expected/task/name/a.txt +0 -1
  227. data/test/test/tap_methods/test_assert_files/expected/task/name/b.txt +0 -1
  228. data/test/test/tap_methods/test_assert_files/input/a.txt +0 -1
  229. data/test/test/tap_methods/test_assert_files/input/b.txt +0 -1
  230. data/test/test/tap_methods_test.rb +0 -399
  231. data/test/workflow_test.rb +0 -120
  232. data/vendor/rails_generator.rb +0 -56
  233. data/vendor/rails_generator/base.rb +0 -263
  234. data/vendor/rails_generator/commands.rb +0 -581
  235. data/vendor/rails_generator/generated_attribute.rb +0 -42
  236. data/vendor/rails_generator/lookup.rb +0 -209
  237. data/vendor/rails_generator/manifest.rb +0 -53
  238. data/vendor/rails_generator/options.rb +0 -143
  239. data/vendor/rails_generator/scripts.rb +0 -83
  240. data/vendor/rails_generator/scripts/destroy.rb +0 -7
  241. data/vendor/rails_generator/scripts/generate.rb +0 -7
  242. data/vendor/rails_generator/scripts/update.rb +0 -12
  243. data/vendor/rails_generator/simple_logger.rb +0 -46
  244. data/vendor/rails_generator/spec.rb +0 -44
@@ -1 +0,0 @@
1
- key: two
@@ -1,2 +0,0 @@
1
- - key: one
2
- - key: two
File without changes
@@ -1,2 +0,0 @@
1
- app: <%= app.object_id %>
2
- filepath: <%= filepath %>
@@ -1 +0,0 @@
1
- key: one
@@ -1,2 +0,0 @@
1
- - factor: 10
2
- - factor: 22
@@ -1 +0,0 @@
1
- version: 0.1
@@ -1 +0,0 @@
1
- version: empty
@@ -1,3 +0,0 @@
1
- require 'tap'
2
- class AppTestTask < Tap::Task
3
- end
data/test/app_test.rb DELETED
@@ -1,1849 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'tap_test_helper')
2
- require 'tap/app'
3
- require 'stringio'
4
- require 'logger'
5
-
6
- class AppTest < Test::Unit::TestCase
7
- include Tap
8
- include TapTestMethods
9
-
10
- acts_as_tap_test
11
-
12
- def setup
13
- super
14
- app.root = trs.root
15
- end
16
-
17
- #
18
- # instance tests
19
- #
20
-
21
- def test_instance_returns_current_instance_or_a_default_app
22
- a = App.new
23
- App.instance = a
24
- assert_equal a, App.instance
25
-
26
- App.instance = nil
27
- assert_equal App, App.instance.class
28
- end
29
-
30
- def test_instance_initializes_new_App_if_not_set
31
- Tap::App.instance = nil
32
- assert Tap::App.instance.kind_of?(Tap::App)
33
- end
34
-
35
- #
36
- # helpers
37
- #
38
-
39
- # def stub_gemspec(name, version)
40
- # spec = Gem::Specification.new
41
- # spec.name = name
42
- # spec.version = version
43
- # spec.loaded_from = "/path/to/gems"
44
- # spec
45
- # end
46
-
47
- def current_threads
48
- threads = []
49
- ObjectSpace.garbage_collect
50
- sleep 0.2 # sleep to give garbage collect time to run
51
-
52
- # JRuby limits ObjectSpace to only work for Class by default
53
- # so this line has to be made less elegant and a little slower
54
- # ObjectSpace.each_object(Thread) {|t| threads << t.object_id}
55
- ObjectSpace.each_object(Class) {|t| threads << t.object_id if t.kind_of?(Thread)}
56
- threads
57
- end
58
-
59
- # check that no new threads are created during the block
60
- def extended_test_with_thread_check
61
- extended_test do
62
- prior_threads = current_threads
63
- yield
64
- assert_equal prior_threads, current_threads
65
- end
66
- end
67
-
68
- def test_app_documentation
69
- pwd = app.root
70
- assert_equal(pwd, app.root)
71
- assert_equal( File.expand_path(pwd +'/config'), app[:config])
72
-
73
- some_task = Task.new 'some/task'
74
- assert_equal( App.instance , some_task.app )
75
- assert_equal( File.expand_path(pwd +'/config/some/task.yml') , some_task.config_file)
76
- assert_equal( {:key => 'one'}, some_task.config)
77
-
78
- another_task = Task.new 'another/task'
79
- assert_equal( App.instance , another_task.app )
80
- assert_equal( File.expand_path(pwd + '/config/another/task.yml') , another_task.config_file)
81
- assert_equal( {:key => 'two'}, another_task.config)
82
-
83
- ###
84
- t1 = Task.new {|task, input| input += 1 }
85
- t1.enq 0
86
- t1.enq 10
87
-
88
- app.run
89
- assert_equal [1, 11], app.results(t1)
90
-
91
- app.aggregator.clear
92
-
93
- t2= Task.new {|task, input| input += 10 }
94
- t1.on_complete {|_result| t2.enq(_result) }
95
-
96
- t1.enq 0
97
- t1.enq 10
98
-
99
- app.run
100
- assert_equal [], app.results(t1)
101
- assert_equal [11, 21], app.results(t2)
102
-
103
- ###
104
- t1 = Task.new {|task, input| input += 1 }
105
- t2 = Task.new {|task, input| input += 10 }
106
- assert_equal [t1, t2], Task.batch(t1, t2)
107
-
108
- t1.enq 0
109
- t2.enq 10
110
-
111
- app.run
112
- assert_equal [1, 11], app.results(t1)
113
- assert_equal [10, 20], app.results(t2)
114
-
115
- lock = Mutex.new
116
- array = []
117
- t1 = Task.new {|task| lock.synchronize { array << Thread.current.object_id }; sleep 0.1 }
118
- t2 = Task.new {|task| lock.synchronize { array << Thread.current.object_id }; sleep 0.1 }
119
-
120
- t1.multithread = true
121
- t1.enq
122
- t2.multithread = true
123
- t2.enq
124
-
125
- app.run
126
- assert_equal 2, array.length
127
- assert_not_equal array[0], array[1]
128
-
129
- array = []
130
- Task::Base.initialize(array, :push)
131
-
132
- array.enq(1)
133
- array.enq(2)
134
-
135
- assert array.empty?
136
- app.run
137
- assert_equal [1, 2], array
138
-
139
- array = []
140
- m = array._method(:push)
141
-
142
- app.enq(m, 1)
143
- app.mq(array, :push, 2)
144
-
145
- assert array.empty?
146
- app.run
147
- assert_equal [1, 2], array
148
-
149
- ###
150
- t1 = Tap::Task.new('add_one') {|task, input| input += 1 }
151
- t2 = Tap::Task.new('add_five') {|task, input| input += 5 }
152
-
153
- t1.on_complete do |_result|
154
- _result._current < 3 ? t1.enq(_result) : t2.enq(_result)
155
- end
156
-
157
- t1.enq(0)
158
- t1.enq(1)
159
- t1.enq(2)
160
-
161
- app.run
162
- assert_equal [8,8,8], app.results(t2)
163
-
164
- strio = StringIO.new("")
165
- app._results(t2).each do |_result|
166
- strio.puts "How #{_result._original} became #{_result._current}:"
167
- strio.puts _result._to_s
168
- strio.puts
169
- end
170
-
171
- assert_equal(
172
- %Q{How 2 became 8:
173
- o-[] 2
174
- o-[add_one] 3
175
- o-[add_five] 8
176
-
177
- How 1 became 8:
178
- o-[] 1
179
- o-[add_one] 2
180
- o-[add_one] 3
181
- o-[add_five] 8
182
-
183
- How 0 became 8:
184
- o-[] 0
185
- o-[add_one] 1
186
- o-[add_one] 2
187
- o-[add_one] 3
188
- o-[add_five] 8
189
-
190
- }, strio.string)
191
-
192
- end
193
-
194
- #
195
- # State test
196
- #
197
-
198
- def test_state_str_documentation
199
- assert_equal 'READY', App::State.state_str(0)
200
- assert_nil App::State.state_str(12)
201
- end
202
-
203
- #
204
- # initialization tests
205
- #
206
-
207
- def test_default_app
208
- app = App.new
209
-
210
- assert_equal Dir.pwd, app.root
211
- assert_equal({}, app.directories)
212
- assert_equal({}, app.options.marshal_dump)
213
- assert_equal({}, app.map)
214
- assert_equal(Support::ExecutableQueue, app.queue.class)
215
- assert app.queue.empty?
216
- assert_equal(Support::Aggregator, app.aggregator.class)
217
- assert app.aggregator.empty?
218
- assert_equal App::State::READY, app.state
219
- end
220
-
221
- #
222
- # task config tests
223
- #
224
-
225
- def test_config_returns_current_configurations
226
- app = App.new
227
- expected = {
228
- :root => Dir.pwd,
229
- :directories => {},
230
- :absolute_paths => {},
231
- :options => {},
232
- :logger => {
233
- :device => STDOUT,
234
- :level => 1, # corresponds to 'INFO'
235
- :datetime_format => '%H:%M:%S'}
236
- }
237
- assert_equal expected, app.config
238
-
239
- # now try with a variety of configurations changed
240
- app.options.trace = true
241
- app[:lib] = 'alt/lib'
242
- app[:abs, true] = '/absolute/path'
243
- strio = StringIO.new('')
244
- app.logger = Logger.new(strio)
245
-
246
- expected = {
247
- :root => Dir.pwd,
248
- :directories => {:lib => 'alt/lib'},
249
- :absolute_paths => {:abs => File.expand_path('/absolute/path')},
250
- :options => {:trace => true},
251
- :logger => {
252
- :device => strio,
253
- :level => 0,
254
- :datetime_format => nil}
255
- }
256
-
257
- assert_equal 0, app.logger.level
258
- assert_equal nil, app.logger.datetime_format
259
- assert_equal expected, app.config
260
- end
261
-
262
- #
263
- # reconfigure test
264
- #
265
-
266
- def test_reconfigure_documentation
267
- app = Tap::App.new :root => "/root", :directories => {:dir => 'path/to/dir'}
268
- app.reconfigure(
269
- :root => "./new/root",
270
- :logger => {:level => Logger::DEBUG})
271
-
272
- assert_equal File.expand_path("./new/root"), app.root
273
- assert_equal File.expand_path("./new/root/path/to/dir"), app[:dir]
274
- assert_equal Logger::DEBUG, app.logger.level
275
- end
276
-
277
- def test_reconfigure_root_sets_app_root
278
- app = App.new
279
-
280
- assert_equal Dir.pwd, app.root
281
- app.reconfigure :root => './alt/root'
282
- assert_equal File.expand_path('./alt/root'), app.root
283
- end
284
-
285
- def test_reconfigure_directories_sets_directories
286
- app = App.new
287
- assert_equal({}, app.directories)
288
- app.reconfigure :directories => {:lib => 'alt/lib'}
289
- assert_equal({:lib => 'alt/lib'}, app.directories)
290
- end
291
-
292
- def test_reconfigure_absolute_paths_sets_absolute_paths
293
- app = App.new
294
- assert_equal({}, app.absolute_paths)
295
- app.reconfigure :absolute_paths => {:log => '/path/to/log'}
296
- assert_equal({:log => File.expand_path('/path/to/log')}, app.absolute_paths)
297
- end
298
-
299
- def test_reconfigure_options_sets_options
300
- app = App.new
301
- assert_equal({}, app.options.marshal_dump)
302
- app.reconfigure :options => {:trace => true}
303
- assert_equal({:trace => true}, app.options.marshal_dump)
304
- end
305
-
306
- def test_reconfigure_logger_sets_logger
307
- app = App.new
308
- assert_equal STDOUT, app.logger.logdev.dev
309
- strio = StringIO.new('')
310
- app.reconfigure :logger => {:device => strio, :level => Logger::WARN}
311
- assert_equal strio, app.logger.logdev.dev
312
- assert_equal Logger::WARN, app.logger.level
313
- end
314
-
315
- def test_reconfigure_map_sets_map
316
- app = App.new
317
- assert_equal({}, app.map)
318
- app.reconfigure :map => {'some/task_name' => Tap::Task}
319
- assert_equal({'some/task_name' => Tap::Task}, app.map)
320
- end
321
-
322
- def test_reconfigure_sends_unhandled_options_to_block_if_given
323
- app = App.new
324
- was_in_block = false
325
- app.reconfigure(:unknown => 'value') do |key, value|
326
- assert_equal(:unknown, key)
327
- assert_equal('value', value)
328
- was_in_block = true
329
- end
330
- assert was_in_block
331
- end
332
-
333
- def test_reconfigure_raises_error_for_unhandled_options
334
- app = App.new
335
- assert_raise(ArgumentError) { app.reconfigure(:unknown => 'value') }
336
- end
337
-
338
- class AppHandlesConfig < App
339
- attr_accessor :handled_configs
340
- def initialize
341
- self.handled_configs = []
342
- end
343
- def handle_configuation(key, value)
344
- handled_configs.concat [key, value]
345
- true
346
- end
347
- end
348
-
349
- def test_reconfigure_sends_unhandled_options_to_handle_configuation_if_defined
350
- app = AppHandlesConfig.new
351
- was_in_block = false
352
- app.reconfigure(:unknown => 'value') do |key, value|
353
- was_in_block = true
354
- end
355
- assert_equal [:unknown, 'value'], app.handled_configs
356
- assert !was_in_block
357
- end
358
-
359
- class AppDoesNotHandleConfig < AppHandlesConfig
360
- def handle_configuation(key, value)
361
- handled_configs.concat [key, value]
362
- false
363
- end
364
- end
365
-
366
- def test_reconfigure_goes_to_block_if_handle_configuration_returns_false
367
- app = AppDoesNotHandleConfig.new
368
- was_in_block = false
369
- app.reconfigure(:unknown => 'value') do |key, value|
370
- was_in_block = true
371
- end
372
- assert_equal [:unknown, 'value'], app.handled_configs
373
- assert was_in_block
374
- end
375
-
376
- #
377
- # reload test
378
- #
379
-
380
- def test_reload_returns_unloaded_constants
381
- app = Tap::App.instance
382
-
383
- Dependencies.clear
384
- assert_equal [], app.reload
385
-
386
- begin
387
- assert !Object.const_defined?("AppTestTask")
388
-
389
- Dependencies.load_paths << app['lib']
390
- app_task_test_mod = AppTestTask
391
-
392
- assert Object.const_defined?("AppTestTask")
393
- assert_equal [:AppTestTask], app.reload.collect {|c| c.to_sym }
394
- assert !Object.const_defined?("AppTestTask")
395
- ensure
396
- Dependencies.clear
397
- Dependencies.load_paths.delete(app['lib'])
398
- end
399
- end
400
-
401
- #
402
- # lookup_const test
403
- #
404
-
405
- def test_lookup_const_does_not_mishandle_top_level_constants
406
- assert !Object.const_defined?('LookupModule')
407
- Object.const_set('LookupModule', Module.new)
408
- assert_raise(Tap::App::LookupError) { app.lookup_const('lookup_module/file') }
409
- end
410
-
411
- #
412
- # set logger tests
413
- #
414
-
415
- def test_set_logger_extends_logger_with_support_logger
416
- output = StringIO.new('')
417
- logger = Logger.new(output)
418
- assert !logger.respond_to?(:section_break)
419
-
420
- app.logger = logger
421
- assert logger.respond_to?(:section_break)
422
- end
423
-
424
- #
425
- # TODO -- Add logging tests
426
- #
427
-
428
- #
429
- # task_class tests
430
- #
431
-
432
- class TaskSubClass < Task
433
- end
434
-
435
- class AnotherTask < Task
436
- end
437
-
438
- def test_task_class_documentation
439
- t_class = app.task_class('tap/file_task')
440
- assert_equal Tap::FileTask, t_class
441
-
442
- app.map = {"mapped-task" => "Tap::FileTask"}
443
- t_class = app.task_class('mapped-task-1.0')
444
- assert_equal Tap::FileTask, t_class
445
- end
446
-
447
- #
448
- # task tests
449
- #
450
-
451
- def test_task_documentation
452
- t = app.task('tap/file_task')
453
- assert_equal Tap::FileTask, t.class
454
- assert_equal 'tap/file_task', t.name
455
-
456
- app.map = {"mapped-task" => "Tap::FileTask"}
457
-
458
- t = app.task('mapped-task-1.0', :key => 'value')
459
- assert_equal Tap::FileTask, t.class
460
- assert_equal "mapped-task-1.0", t.name
461
- assert_equal 'value', t.config[:key]
462
- end
463
-
464
- def test_task_looks_up_and_instantiates_task
465
- assert_equal TaskSubClass, app.task("AppTest::TaskSubClass").class
466
- end
467
-
468
- def test_task_instantiates_a_new_task_for_each_call
469
- t1 = app.task("AppTest::TaskSubClass")
470
- t2 = app.task("AppTest::TaskSubClass")
471
-
472
- assert_not_equal t1.object_id, t2.object_id
473
- end
474
-
475
- def test_task_translates_task_name_to_class_name_using_map_if_possible
476
- app.map["mapped_name"] = "AppTest::TaskSubClass"
477
- assert_equal TaskSubClass, app.task("mapped_name").class
478
- end
479
-
480
- def test_task_translates_task_name_to_class_name_using_camelize_by_default
481
- assert_equal TaskSubClass, app.task("app_test/task_sub_class").class
482
- end
483
-
484
- def test_task_name_and_version_is_respected
485
- t = app.task("app_test/task_sub_class-1.1")
486
- assert_equal TaskSubClass, t.class
487
- assert_equal "app_test/task_sub_class-1.1", t.name
488
- end
489
-
490
- def test_task_looks_up_task_classes_along_Dependencies_load_paths
491
- begin
492
- assert !Object.const_defined?("AppTestTask")
493
-
494
- Dependencies.load_paths << app['lib']
495
- t = app.task("AppTestTask")
496
-
497
- assert Object.const_defined?("AppTestTask")
498
- assert_equal AppTestTask, t.class
499
- ensure
500
- Dependencies.clear
501
- Dependencies.load_paths.delete(app['lib'])
502
- end
503
- end
504
-
505
- def test_task_raises_lookup_error_if_class_cannot_be_found
506
- assert_raise(App::LookupError) { app.task("NonExistant") }
507
- end
508
-
509
- #
510
- # task_class_name test
511
- #
512
-
513
- def test_task_class_name_documentation
514
- app.map = {"mapped-task" => "Tap::FileTask"}
515
- assert_equal "some/task_class", app.task_class_name('some/task_class')
516
- assert_equal "Tap::FileTask", app.task_class_name('mapped-task-1.0')
517
-
518
- t1 = Task.new
519
- assert_equal "Tap::Task", app.task_class_name(t1)
520
-
521
- t2 = ObjectWithExecute.new.extend Tap::Task::Base
522
- assert_equal "ObjectWithExecute", app.task_class_name(t2)
523
- end
524
-
525
- def test_task_class_name_returns_task_class_name
526
- task = Task.new
527
- assert_equal "Tap::Task", app.task_class_name(task)
528
-
529
- subtask = TaskSubClass.new
530
- assert_equal "AppTest::TaskSubClass", app.task_class_name(subtask)
531
-
532
- non_task = ObjectWithExecute.new
533
- non_task.extend Tap::Task::Base
534
- assert_equal "ObjectWithExecute", app.task_class_name(non_task)
535
- end
536
-
537
- def test_task_class_name_returns_deversioned_name
538
- assert_equal "app_test/task_sub_class", app.task_class_name("app_test/task_sub_class-1.1")
539
- end
540
-
541
- def test_task_class_name_resolves_names_using_map
542
- app.map = {"mapped-task" => "AnotherTask"}
543
- assert_equal "AnotherTask", app.task_class_name("mapped-task-1.1")
544
- end
545
-
546
- #
547
- # each_config_template tests
548
- #
549
-
550
- def test_each_config_template_documentation
551
- simple = output_tempfile
552
- File.open(simple, "w") {|f| f << "key: value"}
553
- assert_equal([{"key" => "value"}], app.each_config_template(simple))
554
-
555
- erb = output_tempfile
556
- File.open(erb, "w") {|f| f << "app: <%= app.object_id %>\nfilepath: <%= filepath %>"}
557
- assert_equal([{"app" => app.object_id, "filepath" => erb}], app.each_config_template(erb))
558
-
559
- batched_with_erb = output_tempfile
560
- File.open(batched_with_erb, "w") do |f|
561
- f << %Q{
562
- - key: <%= 1 %>
563
- - key: <%= 1 + 1 %>}
564
- end
565
- assert_equal([{"key" => 1}, {"key" => 2}], app.each_config_template(batched_with_erb))
566
- end
567
-
568
- def test_each_config_template_retrieves_templates_for_versioned_config_files
569
- filepath = app.filepath('config', "version.yml")
570
- assert File.exists?(filepath)
571
- assert_equal [{"version" => "empty"}], app.each_config_template(filepath)
572
-
573
- filepath = app.filepath('config', "version-0.1.yml")
574
- assert File.exists?(filepath)
575
- assert_equal [{"version" => 0.1}], app.each_config_template(filepath)
576
- end
577
-
578
- def test_each_config_template_can_load_an_array_of_templates
579
- filepath = app.filepath('config', "batch.yml")
580
- assert File.exists?(filepath)
581
- assert_equal [{"key" => "one"}, {"key" => "two"}], app.each_config_template(filepath)
582
- end
583
-
584
- def test_each_config_template_returns_empty_template_even_if_config_file_does_not_exist
585
- filepath = app.filepath('config', "non_existant.yml")
586
- assert !File.exists?(filepath)
587
- assert_equal [{}], app.each_config_template(filepath)
588
- end
589
-
590
- def test_each_config_template_returns_empty_template_if_config_file_is_empty
591
- filepath = app.filepath('config', "empty.yml")
592
- assert File.exists?(filepath)
593
- assert_equal "", File.read(filepath)
594
- assert_equal [{}], app.each_config_template(filepath)
595
- end
596
-
597
- def test_each_config_template_templates_using_erb
598
- filepath = app.filepath('config', "erb.yml")
599
- assert_equal [{"filepath" => filepath, "app" => app.object_id}], app.each_config_template(filepath)
600
- end
601
-
602
- #
603
- # config_filepath test
604
- #
605
-
606
- def test_config_filepath
607
- assert_equal nil, app.config_filepath(nil)
608
- assert_equal File.join(app['config'], "task/name.yml"), app.config_filepath("task/name")
609
- end
610
-
611
- #
612
- # ready test
613
- #
614
-
615
- def test_ready_sets_state_to_READY_unless_running
616
- app.instance_variable_set('@state', App::State::STOP)
617
- assert_not_equal App::State::READY, app.state
618
-
619
- assert_equal app, app.ready
620
- assert_equal App::State::READY, app.state
621
- end
622
-
623
- def test_ready_does_not_sets_state_to_READY_when_running
624
- was_in_block = false
625
-
626
- t = Tap::Task.new do |task|
627
- assert_equal App::State::RUN, app.state
628
- task.app.ready
629
- assert_equal App::State::RUN, app.state
630
-
631
- task.app.stop
632
- assert_equal App::State::STOP, app.state
633
- task.app.ready
634
- assert_equal App::State::STOP, app.state
635
-
636
- was_in_block = true
637
- end
638
-
639
- with_options :debug => true do
640
- t.enq
641
- app.run
642
- end
643
-
644
- assert was_in_block
645
- end
646
-
647
- #
648
- # run tests
649
- #
650
-
651
- def test_run_single_task
652
- t = Task.new(&add_one)
653
- with_options :debug => true do
654
- t.enq 1
655
- app.run
656
- end
657
-
658
- assert_audit_equal(ExpAudit[[nil, 1], [t,2]], app._results(t).first)
659
- assert_equal [1], runlist
660
- end
661
-
662
- def test_run_single_task_from_a_thread
663
- t = Task.new(&add_one)
664
- with_options :debug => true do
665
- t.enq 1
666
- th = Thread.new { app.run }
667
- th.join
668
- end
669
-
670
- assert_audit_equal(ExpAudit[[nil, 1], [t,2]], app._results(t).first)
671
- assert_equal [1], runlist
672
- end
673
-
674
- #
675
- # multithread test
676
- #
677
-
678
- def test_main_thread_execution_waits_for_multithread_execution
679
- extended_test do
680
- main_thread_ran = false
681
- check_thread_ran = false
682
- multithread_ran = false
683
-
684
- multithread_executing = false
685
- main_thread_did_not_wait = false
686
- multithread_did_not_wait = false
687
-
688
- t1 = Task.new do |task|
689
- main_thread_ran = true
690
- main_thread_did_not_wait = true if multithread_executing
691
- end
692
-
693
- t2 = Task.new do |task|
694
- check_thread_ran = true
695
- multithread_did_not_wait = true if multithread_executing
696
- end
697
- t2.multithread = true
698
-
699
- t3 = Task.new do |task|
700
- multithread_ran = true
701
- multithread_executing = true
702
-
703
- # sleep is necessary so the other threads
704
- # have an opportunity to execute
705
- sleep(0.1)
706
-
707
- multithread_executing = false
708
- end
709
- t3.multithread = true
710
-
711
- t3.enq
712
- t2.enq
713
- t1.enq
714
-
715
- with_options :debug => true do
716
- app.run
717
- end
718
-
719
- assert main_thread_ran
720
- assert multithread_ran
721
- assert check_thread_ran
722
- assert !main_thread_did_not_wait
723
- assert multithread_did_not_wait
724
- end
725
- end
726
-
727
- def test_multithread_execution_waits_for_main_thread_execution
728
- extended_test do
729
- main_thread_ran = false
730
- multithread_ran = false
731
-
732
- multithread_did_not_wait = false
733
- main_thread_executing = false
734
-
735
- t1 = Task.new do |task|
736
- multithread_ran = true
737
- multithread_did_not_wait = true if main_thread_executing
738
- end
739
- t1.multithread = true
740
-
741
- t2 = Task.new do |task|
742
- main_thread_ran = true
743
- main_thread_executing = true
744
-
745
- # sleep is necessary so the other threads
746
- # have an opportunity to execute
747
- sleep(0.1)
748
-
749
- main_thread_executing = false
750
- end
751
-
752
- t2.enq
753
- t1.enq
754
-
755
- with_options :debug => true do
756
- app.run
757
- end
758
-
759
- assert main_thread_ran
760
- assert multithread_ran
761
- assert !multithread_did_not_wait
762
- end
763
- end
764
-
765
- def test_only_max_threads_will_be_executed_at_a_time
766
- extended_test do
767
- max_threads = 0
768
- n_threads = 0
769
-
770
- # the logic of this test is that if app executes
771
- # in a multithreaded manner, then max_threads will
772
- # be greater than 1. Furthermore, if the max_threads
773
- # option is respected, then max_threads shouldn't be
774
- # greater than 2.
775
- block = lambda do |task|
776
- n_threads += 1
777
- max_threads = n_threads if n_threads > max_threads
778
-
779
- # sleep is necessary so the other threads
780
- # have an opportunity to execute
781
- sleep(0.1)
782
-
783
- n_threads -= 1
784
- nil
785
- end
786
-
787
- t1 = Task.new(&block)
788
- t2 = Task.new(&block)
789
- t3 = Task.new(&block)
790
-
791
- with_options(:max_threads => 2) do
792
- [t1,t2,t3].each do |t|
793
- t.enq
794
- t.multithread = true
795
- end
796
-
797
- with_options :debug => true do
798
- app.run
799
- end
800
-
801
- assert_equal 2, max_threads
802
- end
803
- end
804
- end
805
-
806
- def test_no_new_threads_appear_after_clean_multithread_exit
807
- extended_test_with_thread_check do
808
- max_threads = 0
809
- n_threads = 0
810
-
811
- tasks = Array.new(3) do
812
- Task.new do |task|
813
- n_threads += 1
814
- max_threads = n_threads if n_threads > max_threads
815
- sleep 0.1
816
- n_threads -= 1
817
- end
818
- end
819
- tasks.each do |task|
820
- task.multithread = true
821
- task.enq
822
- end
823
-
824
- app.run
825
-
826
- assert_equal 3, max_threads
827
- end
828
- end
829
-
830
- # JRuby inconsistent test?
831
- # 2 max_threads expected but was 1
832
- def test_no_new_threads_appear_after_clean_main_thread_exit
833
- extended_test_with_thread_check do
834
- max_threads = 0
835
- n_threads = 0
836
-
837
- tasks = Array.new(3) do
838
- Task.new do |task|
839
- n_threads += 1
840
- max_threads = n_threads if n_threads > max_threads
841
- sleep 0.1
842
- n_threads -= 1
843
- end
844
- end
845
- non_threaded = tasks.shift
846
- tasks.each do |task|
847
- task.multithread = true
848
- task.enq
849
- end
850
- non_threaded.enq
851
-
852
- app.run
853
-
854
- assert_equal 2, max_threads
855
- end
856
- end
857
-
858
- #
859
- # stop test
860
- #
861
-
862
- def test_stop_prevents_non_executing_tasks_from_executing_on_main_thread
863
- extended_test_with_thread_check do
864
- count = 0
865
- tasks = Array.new(5) do
866
- Task.new do |task|
867
- count += 1
868
- app.stop if count == 2
869
- end
870
- end
871
- tasks.each do |task|
872
- task.enq
873
- end
874
-
875
- # under these conditions, 2 tasks should be
876
- # executed on 2 threads, and 2 additional tasks
877
- # dequeued into the thread queue. on stop, the 2
878
- # executing tasks should finish normally, and NO MORE
879
- # tasks executed. The waiting tasks will be requeued.
880
- with_options :max_threads => 2, :debug => true do
881
- app.run
882
- end
883
-
884
- assert_equal 2, count
885
- assert_equal 3, app.queue.size
886
-
887
- queued_tasks = []
888
- while !app.queue.empty?
889
- task, inputs = app.queue.deq
890
- queued_tasks << task
891
- end
892
-
893
- # check that the requeued tasks are in order
894
- assert_equal tasks[2...5], queued_tasks
895
- end
896
- end
897
-
898
- def test_stop_prevents_non_executing_tasks_from_executing_on_threads_and_requeues_thread_queue
899
- extended_test_with_thread_check do
900
- count = 0
901
- tasks = Array.new(5) do
902
- Task.new do |task|
903
- count += 1
904
- sleep 0.1
905
- app.stop if count == 2
906
- sleep 0.1
907
- end
908
- end
909
- tasks.each do |task|
910
- task.multithread = true
911
- task.enq
912
- end
913
-
914
- # under these conditions, 2 tasks should be
915
- # executed on 2 threads, and 2 additional tasks
916
- # dequeued into the thread queue. on stop, the 2
917
- # executing tasks should finish normally, and NO MORE
918
- # tasks executed. The waiting tasks will be requeued.
919
- with_options :max_threads => 2, :debug => true do
920
- app.run
921
- end
922
-
923
- assert_equal 2, count
924
- assert_equal 3, app.queue.size
925
-
926
- queued_tasks = []
927
- while !app.queue.empty?
928
- task, inputs = app.queue.deq
929
- queued_tasks << task
930
- end
931
-
932
- # check that the requeued tasks are in order
933
- assert_equal tasks[2...5], queued_tasks
934
- end
935
- end
936
-
937
- #
938
- # terminate test
939
- #
940
-
941
- def test_terminate_from_main_thread_raises_run_error
942
- extended_test_with_thread_check do
943
- was_terminated = true
944
- task = Task.new do |t|
945
- app.terminate
946
- t.check_terminate
947
- was_terminated = false
948
- end
949
-
950
- task.enq
951
- with_options :debug => true do
952
- begin
953
- app.run
954
- flunk "no error was raised"
955
- rescue
956
- assert $!.kind_of?(Tap::Support::RunError)
957
- assert $!.errors.empty?
958
- end
959
- end
960
-
961
- assert was_terminated
962
- end
963
- end
964
-
965
- def test_terminate_from_main_thread_when_error_is_handled_still_raises_error
966
- extended_test_with_thread_check do
967
- terminate_error_handled = false
968
- task = Task.new do |t|
969
- begin
970
- app.terminate
971
- t.check_terminate
972
- rescue
973
- terminate_error_handled = true
974
- end
975
- end
976
-
977
- task.enq
978
- with_options :debug => true do
979
- begin
980
- app.run
981
- flunk "no error was raised"
982
- rescue
983
- assert $!.kind_of?(Tap::Support::RunError)
984
- assert $!.errors.empty?
985
- end
986
- end
987
-
988
- assert terminate_error_handled
989
- end
990
- end
991
-
992
- def test_terminate_raises_error_on_each_execution_thread_and_requeues_thread_queue
993
- extended_test_with_thread_check do
994
- count = 0
995
- some_thread_was_not_terminated = false
996
- tasks = Array.new(5) do
997
- Task.new do |task|
998
- count += 1
999
- app.terminate if count == 2
1000
- sleep 0.8
1001
- task.check_terminate
1002
- some_thread_was_not_terminated = true
1003
- end
1004
- end
1005
- tasks.each do |task|
1006
- task.multithread = true
1007
- task.enq
1008
- end
1009
-
1010
- # under these conditions, 2 tasks should be
1011
- # executed on 2 threads, and 2 additional tasks
1012
- # dequeued into the thread queue. on stop, the 2
1013
- # executing tasks should be terminated, and NO MORE
1014
- # tasks executed. The waiting tasks will be requeued.
1015
- with_options :max_threads => 2, :debug => true do
1016
- begin
1017
- app.run
1018
- flunk "no error was raised"
1019
- rescue
1020
- assert $!.kind_of?(Tap::Support::RunError)
1021
- assert $!.errors.empty?
1022
- end
1023
- end
1024
-
1025
- assert_equal 2, count
1026
- assert_equal 3, app.queue.size
1027
- assert !some_thread_was_not_terminated
1028
-
1029
- queued_tasks = []
1030
- while !app.queue.empty?
1031
- task, inputs = app.queue.deq
1032
- queued_tasks << task
1033
- end
1034
-
1035
- # check that the requeued tasks are in order
1036
- assert_equal tasks[2...5], queued_tasks
1037
- end
1038
- end
1039
-
1040
- # JRuby inconsistent test
1041
- # RESOLVED? 2008/01/29
1042
- # -- still can be an issue, if the sleep time is too short --
1043
- def test_terminate_on_thread_when_error_is_handled_still_raises_error
1044
- extended_test_with_thread_check do
1045
- count = 0
1046
- some_thread_was_not_terminated = false
1047
- handled_count = 0
1048
-
1049
- tasks = Array.new(5) do
1050
- Task.new do |task|
1051
- count += 1
1052
- begin
1053
- app.terminate if count == 2
1054
- sleep 0.8
1055
- task.check_terminate
1056
- some_thread_was_not_terminated = true
1057
- rescue
1058
- handled_count += 1
1059
- end
1060
- end
1061
- end
1062
- tasks.each do |task|
1063
- task.multithread = true
1064
- task.enq
1065
- end
1066
-
1067
- # under these conditions, 2 tasks should be
1068
- # executed on 2 threads, and 2 additional tasks
1069
- # dequeued into the thread queue. on stop, the 2
1070
- # executing tasks should be terminated, and NO MORE
1071
- # tasks executed. The waiting tasks will be requeued.
1072
- with_options :max_threads => 2, :debug => true do
1073
- begin
1074
- app.run
1075
- flunk "no error was raised"
1076
- rescue
1077
- assert $!.kind_of?(Tap::Support::RunError)
1078
- assert $!.errors.empty?
1079
- end
1080
- end
1081
-
1082
- assert !some_thread_was_not_terminated
1083
- assert_equal 2, count
1084
- assert_equal 2, handled_count
1085
- assert_equal 3, app.queue.size
1086
- end
1087
- end
1088
-
1089
- #
1090
- # info tests
1091
- #
1092
-
1093
- def test_info_provides_information_string
1094
- assert_equal 'state: 0 (READY) queue: 0 thread_queue: 0 threads: 0 results: 0', app.info
1095
- end
1096
-
1097
- # TODO -- JRuby inconsistent test
1098
- # RESOLVED? 2007/01/30
1099
- def test_info_can_be_called_during_a_run
1100
- extended_test do
1101
- lock = Monitor.new
1102
- count = 0
1103
- info_str = nil
1104
-
1105
- tasks = Array.new(5) do
1106
- Task.new do |task|
1107
-
1108
- lock.synchronize do
1109
- count += 1
1110
- if count == 2
1111
- info_str = app.info
1112
- app.stop
1113
- end
1114
- end
1115
-
1116
- sleep 0.8
1117
- end
1118
- end
1119
- tasks.each do |task|
1120
- task.enq
1121
- task.multithread = true
1122
- end
1123
-
1124
- with_options :max_threads => 2 do
1125
- app.run
1126
- end
1127
-
1128
- # There is some ambiguity in the info string -- tasks
1129
- # could be waiting in the queue or in the thread queue
1130
- # and additionally, the thread queue may have nils to
1131
- # signal the threads to terminate
1132
- assert info_str =~ /state: 1 \(RUN\) queue: \d thread_queue: \d threads: 2 results: \d/, info_str
1133
- assert_equal 'state: 0 (READY) queue: 3 thread_queue: 0 threads: 0 results: 2', app.info
1134
- end
1135
- end
1136
-
1137
- #
1138
- # enq test
1139
- #
1140
-
1141
- def test_enq
1142
- t = Task.new
1143
- assert app.queue.empty?
1144
- app.enq(t)
1145
- assert_equal [[t, []]], app.queue.to_a
1146
- end
1147
-
1148
- def test_enq_enques_each_task_in_task_batch
1149
- t1 = Task.new
1150
- t2 = t1.initialize_batch_obj
1151
-
1152
- assert app.queue.empty?
1153
- app.enq(t1)
1154
- assert_equal [[t1, []], [t2, []]], app.queue.to_a
1155
- end
1156
-
1157
- def test_enq_allows_methods
1158
- m = []._method(:push)
1159
- assert app.queue.empty?
1160
- app.enq(m)
1161
- assert_equal [[m, []]], app.queue.to_a
1162
- end
1163
-
1164
- def test_enq_returns_enqued_task
1165
- t = Task.new
1166
- assert_equal t, app.enq(t)
1167
- end
1168
-
1169
- #
1170
- # mq test
1171
- #
1172
-
1173
- def test_mq
1174
- a = []
1175
- assert app.queue.empty?
1176
- m = app.mq(a, :push, 1, 2)
1177
- assert_equal [[m, [1,2]]], app.queue.to_a
1178
- end
1179
-
1180
- # #
1181
- # # on_complete tests
1182
- # #
1183
- #
1184
- # def test_on_complete
1185
- # t1 = Task.new(&add_one)
1186
- # t2 = Task.new(&add_one)
1187
- # t3 = Task.new(&add_one)
1188
- #
1189
- # app.on_complete(t1) do |result|
1190
- # t2.enq result
1191
- # t3.enq result
1192
- # end
1193
- # with_options :debug => true do
1194
- # t1.enq 0
1195
- # app.run
1196
- # end
1197
- #
1198
- # assert_equal [0,1,1], runlist
1199
- # assert_audit_equal(ExpAudit[[nil,0],[t1,1],[t2,2]], app._results(t2).first)
1200
- # assert_audit_equal(ExpAudit[[nil,0],[t1,1],[t3,2]], app._results(t3).first)
1201
- # end
1202
-
1203
- #
1204
- # sequence tests
1205
- #
1206
-
1207
- def test_run_sequence
1208
- t1 = Task.new(&add_one)
1209
- t2 = Task.new(&add_one)
1210
-
1211
- app.sequence(t1,t2)
1212
- with_options :debug => true do
1213
- t1.enq 0
1214
- app.run
1215
- end
1216
-
1217
- assert_equal [0,1], runlist
1218
- assert_audit_equal(ExpAudit[[nil,0],[t1,1],[t2,2]], app._results(t2).first)
1219
- end
1220
-
1221
- def test_run_sequence_from_trailing_task
1222
- t1 = Task.new(&add_one)
1223
- t2 = Task.new(&add_one)
1224
-
1225
- app.sequence(t1,t2)
1226
- with_options :debug => true do
1227
- t2.enq 1
1228
- app.run
1229
- end
1230
-
1231
- assert_equal [1], runlist
1232
- assert_equal 0, app._results(t1).length
1233
- assert_audit_equal(ExpAudit[[nil,1],[t2,2]], app._results(t2).first)
1234
- end
1235
-
1236
- #
1237
- # fork tests
1238
- #
1239
-
1240
- def test_run_fork
1241
- t1 = Task.new(&add_one)
1242
- t2 = Task.new(&add_one)
1243
- t3 = Task.new(&add_one)
1244
-
1245
- app.fork(t1, t2, t3)
1246
- with_options :debug => true do
1247
- t1.enq 0
1248
- app.run
1249
- end
1250
-
1251
- assert_equal [0,1,1], runlist
1252
- assert_audit_equal(ExpAudit[[nil,0],[t1,1],[t2,2]], app._results(t2).first)
1253
- assert_audit_equal(ExpAudit[[nil,0],[t1,1],[t3,2]], app._results(t3).first)
1254
- end
1255
-
1256
- #
1257
- # merge tests
1258
- #
1259
-
1260
- def test_run_merge
1261
- t1 = Task.new(&add_one)
1262
- t2 = Task.new(&add_one)
1263
- t3 = Task.new(&add_one)
1264
-
1265
- app.merge(t3, t1, t2)
1266
- with_options :debug => true do
1267
- t1.enq 0
1268
- t2.enq 10
1269
- app.run
1270
- end
1271
-
1272
- assert_equal [0,10,1,11], runlist
1273
-
1274
- assert_audits_equal([
1275
- ExpAudit[[nil,0],[t1,1],[t3,2]],
1276
- ExpAudit[[nil,10],[t2,11],[t3,12]]
1277
- ], app._results(t3))
1278
- end
1279
-
1280
- #
1281
- # run batched task tests
1282
- #
1283
-
1284
- def test_run_batched_task
1285
- t1 = Task.new('template') do |task, input|
1286
- runlist << input
1287
- input + task.config[:factor]
1288
- end
1289
- assert_equal 2, t1.batch.length
1290
-
1291
- t1_0 = t1.batch[0]
1292
- t1_1 = t1.batch[1]
1293
-
1294
- assert_equal 10, t1_0.config[:factor]
1295
- assert_equal 22, t1_1.config[:factor]
1296
-
1297
- with_options :debug => true do
1298
- t1.enq 0
1299
- app.run
1300
- end
1301
-
1302
- # note same input fed to each template
1303
- assert_equal [0,0], runlist
1304
-
1305
- assert_audits_equal([
1306
- ExpAudit[[nil,0],[t1_0,10]],
1307
- ExpAudit[[nil,0],[t1_1,22]]
1308
- ], app._results(*t1.batch))
1309
- end
1310
-
1311
- def test_run_batched_task_with_existing_audit_trails
1312
- t1 = Task.new('template') do |task, input|
1313
- runlist << input
1314
- input + task.config[:factor]
1315
- end
1316
- assert_equal 2, t1.batch.length
1317
-
1318
- t1_0 = t1.batch[0]
1319
- t1_1 = t1.batch[1]
1320
-
1321
- assert_equal 10, t1_0.config[:factor]
1322
- assert_equal 22, t1_1.config[:factor]
1323
-
1324
- a = Support::Audit.new(0, :a)
1325
- with_options :debug => true do
1326
- t1.enq a
1327
- app.run
1328
- end
1329
-
1330
- # note same input fed to each template
1331
- assert_equal [0,0], runlist
1332
-
1333
- assert_audits_equal([
1334
- ExpAudit[[:a,0],[t1_0,10]],
1335
- ExpAudit[[:a,0],[t1_1,22]]
1336
- ], app._results(t1.batch))
1337
- end
1338
-
1339
- # TODO -- JRuby inconsistent test
1340
- # RESOLVED? 2007/01/30
1341
- def test_multithread_batched_tasks_execute_cosynchronously
1342
- extended_test do
1343
- lock = Monitor.new
1344
- max_threads = 0
1345
- n_threads = 0
1346
-
1347
- block = lambda do |task|
1348
- lock.synchronize do
1349
- n_threads += 1
1350
- max_threads = n_threads if n_threads > max_threads
1351
- end
1352
-
1353
- # sleep is necessary so the other threads
1354
- # have an opportunity to execute
1355
- sleep(0.1)
1356
-
1357
- lock.synchronize { n_threads -= 1 }
1358
- nil
1359
- end
1360
-
1361
- t1 = Task.new(&block)
1362
- t1.initialize_batch_obj
1363
-
1364
- assert_equal 2, t1.batch.length
1365
- t1.multithread = true
1366
- t1.enq
1367
-
1368
- with_options :debug => true do
1369
- app.run
1370
- end
1371
- assert_equal 2, max_threads
1372
- end
1373
- end
1374
-
1375
- def test_fork_in_batched_task
1376
- t1, t2, t3 = Array.new(3) do
1377
- t = Task.new(nil, :factor => 10) do |task, input|
1378
- runlist << input
1379
- input + task.config[:factor]
1380
- end
1381
- t.initialize_batch_obj(nil, :factor => 22)
1382
- end
1383
-
1384
- app.fork(t1, t2, t3)
1385
- with_options :debug => true do
1386
- t1.enq 0
1387
- app.run
1388
- end
1389
-
1390
- assert_equal [
1391
- 0,0, # once for each t1 template
1392
- 10,10, 10,10, # first result into t2, t3 tasks
1393
- 22,22, 22,22 # second result into t2, t3 tasks
1394
- ], runlist
1395
-
1396
- t1_0 = t1.batch[0]
1397
- t1_1 = t1.batch[1]
1398
-
1399
- t2_0 = t2.batch[0]
1400
- t2_1 = t2.batch[1]
1401
-
1402
- t3_0 = t3.batch[0]
1403
- t3_1 = t3.batch[1]
1404
-
1405
- # check t2 results
1406
- assert_audits_equal([
1407
- ExpAudit[[nil,0],[t1_0,10],[t2_0,20]],
1408
- ExpAudit[[nil,0],[t1_1,22],[t2_0,32]],
1409
- ExpAudit[[nil,0],[t1_0,10],[t2_1,32]],
1410
- ExpAudit[[nil,0],[t1_1,22],[t2_1,44]]
1411
- ], app._results(t2.batch))
1412
-
1413
- # check t3 results
1414
- assert_audits_equal([
1415
- ExpAudit[[nil,0],[t1_0,10],[t3_0,20]],
1416
- ExpAudit[[nil,0],[t1_1,22],[t3_0,32]],
1417
- ExpAudit[[nil,0],[t1_0,10],[t3_1,32]],
1418
- ExpAudit[[nil,0],[t1_1,22],[t3_1,44]]
1419
- ], app._results(t3.batch))
1420
- end
1421
-
1422
- def test_merge_batched_task
1423
- t1, t2, t3 = Array.new(3) do
1424
- t = Task.new(nil, :factor => 10) do |task, input|
1425
- runlist << input
1426
- input + task.config[:factor]
1427
- end
1428
- t.initialize_batch_obj(nil, :factor => 22)
1429
- end
1430
-
1431
- app.merge(t3, t1, t2)
1432
- t1.enq(0)
1433
- t2.enq(2)
1434
- with_options :debug => true do
1435
- app.run
1436
- end
1437
-
1438
- assert_equal [
1439
- 0,0, # 1 input to each t1
1440
- 2,2, # 2 input to each t2
1441
- 10,10,22,22, # t1 outputs to each t3
1442
- 12,12,24,24 # t2 outputs to each t3
1443
- ], runlist
1444
-
1445
- t1_0 = t1.batch[0]
1446
- t1_1 = t1.batch[1]
1447
-
1448
- t2_0 = t2.batch[0]
1449
- t2_1 = t2.batch[1]
1450
-
1451
- t3_0 = t3.batch[0]
1452
- t3_1 = t3.batch[1]
1453
-
1454
- # check results
1455
- assert_audits_equal([
1456
- ExpAudit[[nil,0],[t1_0,10],[t3_0,20]],
1457
- ExpAudit[[nil,0],[t1_1,22],[t3_0,32]],
1458
- ExpAudit[[nil,2],[t2_0,12],[t3_0,22]],
1459
- ExpAudit[[nil,2],[t2_1,24],[t3_0,34]],
1460
- ExpAudit[[nil,0],[t1_0,10],[t3_1,32]],
1461
- ExpAudit[[nil,0],[t1_1,22],[t3_1,44]],
1462
- ExpAudit[[nil,2],[t2_0,12],[t3_1,34]],
1463
- ExpAudit[[nil,2],[t2_1,24],[t3_1,46]]
1464
- ], app._results(t3.batch))
1465
- end
1466
-
1467
- #
1468
- # other run tests
1469
- #
1470
-
1471
- def test_feedback_loop
1472
- t1 = Task.new(&add_one)
1473
- t2 = Task.new(&add_one)
1474
- t3 = Task.new(&add_one)
1475
-
1476
- # distribute the results of t1 based on value
1477
- t1.on_complete do |result|
1478
- if result._current < 4
1479
- t2.enq result
1480
- else
1481
- t3.enq result
1482
- end
1483
- end
1484
-
1485
- # set the results of t2 to reinvoke the workflow
1486
- app.sequence(t2, t1)
1487
-
1488
- with_options :debug => true do
1489
- t1.enq(0)
1490
- t1.enq(2)
1491
- app.run
1492
- end
1493
-
1494
- assert_equal [0,2,1,3,2,4,3,5,4,5], runlist
1495
-
1496
- assert_audits_equal([
1497
- ExpAudit[[nil,2],[t1,3],[t2,4],[t1,5],[t3,6]],
1498
- ExpAudit[[nil,0],[t1,1],[t2,2],[t1,3],[t2,4],[t1,5],[t3,6]]
1499
- ], app._results(t3.batch))
1500
- end
1501
-
1502
- #
1503
- # _results test
1504
- #
1505
-
1506
- def test__results_returns_audited_results_for_listed_sources
1507
- t1 = Task.new {|task, input| input + 1 }
1508
- a1 = t1._execute(0)
1509
-
1510
- t2 = Task.new {|task, input| input + 1 }
1511
- a2 = t2._execute(1)
1512
-
1513
- app.aggregator.store a1
1514
- app.aggregator.store a2
1515
- assert_equal [a1], app._results(t1)
1516
- assert_equal [a2, a1], app._results(t2, t1)
1517
- assert_equal [a1, a1], app._results(t1, t1)
1518
- end
1519
-
1520
- #
1521
- # results test
1522
- #
1523
-
1524
- def test_results_documentation
1525
- t1 = Task.new {|task, input| input += 1 }
1526
- t2 = Task.new {|task, input| input += 10 }
1527
- t3 = t2.initialize_batch_obj
1528
-
1529
- t1.enq(0)
1530
- t2.enq(1)
1531
-
1532
- app.run
1533
- assert_equal [1, 11, 11], app.results(t1, t2.batch)
1534
- assert_equal [11, 1], app.results(t2, t1)
1535
- end
1536
-
1537
- def test_results_returns_current_values_of__results
1538
- t1 = Task.new {|task, input| input + 1 }
1539
- a1 = t1._execute(0)
1540
-
1541
- t2 = Task.new {|task, input| input + 1 }
1542
- a2 = t2._execute(1)
1543
-
1544
- app.aggregator.store a1
1545
- app.aggregator.store a2
1546
- assert_equal [1], app.results(t1)
1547
- assert_equal [2, 1], app.results(t2, t1)
1548
- assert_equal [1, 1], app.results(t1, t1)
1549
- end
1550
-
1551
- def test_results_for_various_objects
1552
- t1 = Task.new {|task, input| input}
1553
-
1554
- t1.enq({:key => 'value'})
1555
- t1.enq([1,2,3])
1556
- t1.enq(2)
1557
- t1.enq("str")
1558
-
1559
- app.run
1560
- assert_equal [{:key => 'value'}, [1,2,3], 2, "str"], app.results(t1)
1561
- end
1562
-
1563
- #
1564
- # synchronization tests
1565
- #
1566
-
1567
- def test_task_may_be_queued_from_task_while_task_is_running
1568
- count = 0
1569
- counter = Task.new do |task|
1570
- count += 1
1571
- counter.enq if count < 3
1572
- end
1573
-
1574
- with_options :debug => true do
1575
- counter.enq
1576
- app.run
1577
- end
1578
-
1579
- assert_equal 3, count
1580
- end
1581
-
1582
- def test_task_can_queue_from_within_threaded_and_unthreaded_tasks
1583
- threaded_count = 0
1584
- threaded = Task.new do |task|
1585
- runlist << "t"
1586
- threaded_count += 1
1587
- threaded.enq if threaded_count < 3
1588
- end
1589
-
1590
- not_threaded_count = 0
1591
- not_threaded = Task.new do |task|
1592
- runlist << "n"
1593
- not_threaded_count += 1
1594
- not_threaded.enq if not_threaded_count < 3
1595
- end
1596
-
1597
- threaded.multithread = true
1598
- threaded.enq
1599
- not_threaded.enq
1600
-
1601
- with_options :debug => true do
1602
- app.run
1603
- end
1604
-
1605
- assert_equal [
1606
- "t", "n",
1607
- "t", "n",
1608
- "t", "n"], runlist
1609
- assert_equal 3, threaded_count
1610
- assert_equal 3, not_threaded_count
1611
- end
1612
-
1613
- def test_run_is_allowed_within_non_threaded_task
1614
- t2 = Task.new(&add_one)
1615
- t1 = Task.new do |task, input|
1616
- runlist << input
1617
- t2.enq input
1618
- app.run
1619
-
1620
- input += 1
1621
- end
1622
-
1623
- with_options :debug => true do
1624
- t1.enq 0
1625
- app.run
1626
- end
1627
-
1628
- assert_equal [0,0], runlist
1629
- assert_audit_equal(ExpAudit[[nil,0],[t1,1]], app._results(t1).first)
1630
- assert_audit_equal(ExpAudit[[nil,0],[t2,1]], app._results(t2).first)
1631
- end
1632
-
1633
- def test_run_is_allowed_within_threaded_task
1634
- t2 = Task.new(&add_one)
1635
- t1 = Task.new do |task, input|
1636
- runlist << input
1637
- t2.enq input
1638
- app.run
1639
-
1640
- input += 1
1641
- end
1642
-
1643
- t1.multithread = true
1644
- t2.multithread = true
1645
- with_options :debug => true do
1646
- t1.enq 0
1647
- app.run
1648
- end
1649
-
1650
- assert_equal [0,0], runlist
1651
- assert_audit_equal(ExpAudit[[nil,0],[t1,1]], app._results(t1).first)
1652
- assert_audit_equal(ExpAudit[[nil,0],[t2,1]], app._results(t2).first)
1653
- end
1654
-
1655
- #
1656
- # error tests
1657
- #
1658
-
1659
- def set_stringio_logger
1660
- output = StringIO.new('')
1661
- app.logger = Logger.new(output)
1662
- output.string
1663
- end
1664
-
1665
- def test_unhandled_exception_on_main_thread_is_logged_by_default
1666
- task = Task.new {|t| raise "error"}
1667
-
1668
- string = set_stringio_logger
1669
- task.enq
1670
- app.run
1671
-
1672
- assert string =~ /RuntimeError error/
1673
- end
1674
-
1675
- def test_unhandled_exception_raises_run_error_on_main_thread_when_debug
1676
- task = Task.new {|t| raise "error"}
1677
-
1678
- with_options :debug => true do
1679
- begin
1680
- task.enq
1681
- app.run
1682
- flunk "no error was raised"
1683
- rescue
1684
- assert $!.kind_of?(Tap::Support::RunError)
1685
- assert_equal 1 , $!.errors.length
1686
- assert $!.errors[0].kind_of?(RuntimeError)
1687
- assert_equal "error", $!.errors[0].message
1688
- end
1689
- end
1690
- end
1691
-
1692
- def test_unhandled_exception_on_thread_is_logged_by_default
1693
- task = Task.new {|t| raise "error"}
1694
- task.multithread = true
1695
-
1696
- string = set_stringio_logger
1697
- task.enq
1698
- app.run
1699
-
1700
- assert string =~ /RuntimeError error/
1701
- end
1702
-
1703
- # Ruby inconsistent test
1704
- # <"error"> expected but was
1705
- # <"Tap::App::TerminateError">.
1706
- # RESOLVED? -- 2008/01/29
1707
- #
1708
- def test_unhandled_exception_raises_run_error_on_thread_when_debug
1709
- task = Task.new {|t| raise "error"}
1710
- task.multithread = true
1711
-
1712
- with_options :debug => true do
1713
- begin
1714
- task.enq
1715
- app.run
1716
- flunk "no error was raised"
1717
- rescue
1718
- assert $!.kind_of?(Tap::Support::RunError)
1719
- assert_equal 1 , $!.errors.length
1720
- assert $!.errors[0].kind_of?(RuntimeError)
1721
- assert_equal "error", $!.errors[0].message
1722
- end
1723
- end
1724
- end
1725
-
1726
- # Ruby inconsistent test
1727
- # <"error"> expected but was
1728
- # <"Tap::App::TerminateError">.
1729
- # RESOLVED? -- 2008/01/29
1730
- #
1731
- def test_unhandled_exception_on_thread_teminates_threads
1732
- extended_test do
1733
- count = 0
1734
- terminated_count = 0
1735
-
1736
- tasks = Array.new(2) do
1737
- Task.new do |t|
1738
- # count to make sure the tasks actually executed
1739
- count += 1
1740
-
1741
- terminated_count += 1
1742
- sleep 0.8
1743
- t.check_terminate
1744
-
1745
- # this should not happen
1746
- terminated_count -= 1
1747
- end
1748
- end
1749
- terr = Task.new {|t| raise "error"}
1750
-
1751
- tasks << terr
1752
- tasks.each do |task|
1753
- task.multithread = true
1754
- task.enq
1755
- end
1756
-
1757
- with_options :debug => true do
1758
- begin
1759
- app.run
1760
- flunk "no error was raised"
1761
- rescue
1762
- assert $!.kind_of?(Tap::Support::RunError)
1763
- assert_equal 1 , $!.errors.length
1764
- assert $!.errors[0].kind_of?(RuntimeError)
1765
- assert_equal "error", $!.errors[0].message
1766
- end
1767
- end
1768
-
1769
- assert_equal 2, count
1770
- assert_equal 2, terminated_count
1771
- end
1772
- end
1773
-
1774
- # Ruby inconsistent test
1775
- # <"error"> expected but was
1776
- # <"Tap::App::TerminateError">.
1777
- #
1778
- # <"term error 0"> expected but was
1779
- # <"term error 1">.
1780
- # RESOLVED? -- 2008/01/29
1781
- #
1782
- # JRuby inconsistent test
1783
- # RESOLVED? -- 2008/01/30
1784
- #
1785
- def test_exceptions_from_handling_termination_error_are_collected
1786
- extended_test do
1787
- lock = Monitor.new
1788
- count = 0
1789
- count_in_threaded_error_handling = 0
1790
-
1791
- tasks = Array.new(2) do
1792
- Task.new do |t|
1793
- n = nil
1794
- lock.synchronize do
1795
- n = count
1796
- count += 1
1797
- end
1798
-
1799
- sleep 0.8
1800
-
1801
- begin
1802
- t.check_terminate
1803
- rescue
1804
- lock.synchronize { count_in_threaded_error_handling += 1 }
1805
- raise "term error #{n}"
1806
- end
1807
- end
1808
- end
1809
- terr = Task.new {|t| raise "error"}
1810
-
1811
- tasks << terr
1812
- tasks.each do |task|
1813
- task.multithread = true
1814
- task.enq
1815
- end
1816
-
1817
- with_options :debug => true do
1818
- begin
1819
- app.run
1820
- flunk "no error was raised"
1821
- rescue
1822
- assert $!.kind_of?(Tap::Support::RunError)
1823
- assert_equal 3, $!.errors.length
1824
- $!.errors.each {|error| assert error.kind_of?(RuntimeError) }
1825
- messages = $!.errors.collect {|error| error.message}.sort
1826
- assert_equal ["error", "term error 0", "term error 1"], messages
1827
- end
1828
-
1829
- assert_equal 2, count
1830
- assert_equal 2, count_in_threaded_error_handling
1831
- end
1832
- end
1833
- end
1834
-
1835
- #
1836
- # benchmarks
1837
- #
1838
-
1839
- def test_run_speed
1840
- t = Tap::Task.new
1841
- benchmark_test(20) do |x|
1842
- n = 10000
1843
-
1844
- x.report("10k enq ") { n.times { t.enq(1) } }
1845
- x.report("10k run ") { n.times {}; app.run }
1846
- x.report("10k _execute ") { n.times { t._execute(1) } }
1847
- end
1848
- end
1849
- end