fairchild-poolparty 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (519) hide show
  1. data/History.txt +35 -0
  2. data/License.txt +20 -0
  3. data/PostInstall.txt +19 -0
  4. data/README.txt +77 -0
  5. data/Rakefile +45 -0
  6. data/VERSION.yml +4 -0
  7. data/bin/cloud +32 -0
  8. data/bin/cloud-bootstrap +21 -0
  9. data/bin/cloud-configure +28 -0
  10. data/bin/cloud-console +12 -0
  11. data/bin/cloud-contract +17 -0
  12. data/bin/cloud-expand +19 -0
  13. data/bin/cloud-handle-load +27 -0
  14. data/bin/cloud-list +23 -0
  15. data/bin/cloud-osxcopy +17 -0
  16. data/bin/cloud-provision +30 -0
  17. data/bin/cloud-rsync +28 -0
  18. data/bin/cloud-run +18 -0
  19. data/bin/cloud-setup-dev +25 -0
  20. data/bin/cloud-show +27 -0
  21. data/bin/cloud-spec +41 -0
  22. data/bin/cloud-ssh +23 -0
  23. data/bin/cloud-start +28 -0
  24. data/bin/cloud-stats +17 -0
  25. data/bin/cloud-terminate +20 -0
  26. data/bin/ec2-list-active +24 -0
  27. data/bin/messenger-get-current-nodes +14 -0
  28. data/bin/pool +31 -0
  29. data/bin/pool-describe +8 -0
  30. data/bin/pool-generate +18 -0
  31. data/bin/pool-init +28 -0
  32. data/bin/pool-list +30 -0
  33. data/bin/pool-start +26 -0
  34. data/bin/server-become-master +24 -0
  35. data/bin/server-build-messenger +28 -0
  36. data/bin/server-butterfly +25 -0
  37. data/bin/server-clean-cert-for +15 -0
  38. data/bin/server-cloud-elections +26 -0
  39. data/bin/server-ensure-provisioning +38 -0
  40. data/bin/server-fire-cmd +14 -0
  41. data/bin/server-get-load +15 -0
  42. data/bin/server-list-active +26 -0
  43. data/bin/server-list-instances +15 -0
  44. data/bin/server-manage-election +67 -0
  45. data/bin/server-monitor.ru +25 -0
  46. data/bin/server-provision +32 -0
  47. data/bin/server-query-agent +15 -0
  48. data/bin/server-rerun +23 -0
  49. data/bin/server-send-command +18 -0
  50. data/bin/server-show-stats +17 -0
  51. data/bin/server-start-agent +15 -0
  52. data/bin/server-start-client +29 -0
  53. data/bin/server-start-master +26 -0
  54. data/bin/server-start-node +32 -0
  55. data/bin/server-stop-client +3 -0
  56. data/bin/server-stop-master +3 -0
  57. data/bin/server-stop-node +3 -0
  58. data/bin/server-update-hosts +49 -0
  59. data/bin/server-write-new-nodes +26 -0
  60. data/config/jeweler.rb +43 -0
  61. data/config/requirements.rb +7 -0
  62. data/examples/basic.rb +23 -0
  63. data/examples/deploy.rb +5 -0
  64. data/examples/fairchild.rb +32 -0
  65. data/examples/fairchild_chef.rb +19 -0
  66. data/examples/paparazzi.conf.erb +21 -0
  67. data/examples/plugin_without_plugin_directory.rb +12 -0
  68. data/examples/poolparty.rb +12 -0
  69. data/generators/poolspec/USAGE +5 -0
  70. data/generators/poolspec/poolspec_generator.rb +58 -0
  71. data/generators/poolspec/templates/pool_spec_template.erb +9 -0
  72. data/lib/erlang/messenger/Emakefile +1 -0
  73. data/lib/erlang/messenger/Makefile +15 -0
  74. data/lib/erlang/messenger/README +5 -0
  75. data/lib/erlang/messenger/Rakefile +72 -0
  76. data/lib/erlang/messenger/control +11 -0
  77. data/lib/erlang/messenger/ebin/client.app +19 -0
  78. data/lib/erlang/messenger/ebin/master.app +19 -0
  79. data/lib/erlang/messenger/ebin/node.app +19 -0
  80. data/lib/erlang/messenger/ebin/packager.app +19 -0
  81. data/lib/erlang/messenger/ebin/pm_client_rel-0.1.rel +1 -0
  82. data/lib/erlang/messenger/ebin/pm_master_rel-0.1.rel +1 -0
  83. data/lib/erlang/messenger/ebin/pm_node_rel-0.1.rel +1 -0
  84. data/lib/erlang/messenger/include/defines.hrl +27 -0
  85. data/lib/erlang/messenger/lib/eunit/AUTHORS +2 -0
  86. data/lib/erlang/messenger/lib/eunit/CHANGELOG +14 -0
  87. data/lib/erlang/messenger/lib/eunit/COPYING +504 -0
  88. data/lib/erlang/messenger/lib/eunit/Makefile +28 -0
  89. data/lib/erlang/messenger/lib/eunit/NOTES +276 -0
  90. data/lib/erlang/messenger/lib/eunit/README +3 -0
  91. data/lib/erlang/messenger/lib/eunit/doc/edoc-info +3 -0
  92. data/lib/erlang/messenger/lib/eunit/doc/erlang.png +0 -0
  93. data/lib/erlang/messenger/lib/eunit/doc/eunit.html +172 -0
  94. data/lib/erlang/messenger/lib/eunit/doc/index.html +17 -0
  95. data/lib/erlang/messenger/lib/eunit/doc/modules-frame.html +12 -0
  96. data/lib/erlang/messenger/lib/eunit/doc/overview-summary.html +984 -0
  97. data/lib/erlang/messenger/lib/eunit/doc/overview.edoc +980 -0
  98. data/lib/erlang/messenger/lib/eunit/doc/packages-frame.html +11 -0
  99. data/lib/erlang/messenger/lib/eunit/doc/stylesheet.css +55 -0
  100. data/lib/erlang/messenger/lib/eunit/ebin/autoload.beam +0 -0
  101. data/lib/erlang/messenger/lib/eunit/ebin/code_monitor.beam +0 -0
  102. data/lib/erlang/messenger/lib/eunit/ebin/eunit.app +21 -0
  103. data/lib/erlang/messenger/lib/eunit/ebin/eunit.appup +1 -0
  104. data/lib/erlang/messenger/lib/eunit/ebin/eunit.beam +0 -0
  105. data/lib/erlang/messenger/lib/eunit/ebin/eunit_autoexport.beam +0 -0
  106. data/lib/erlang/messenger/lib/eunit/ebin/eunit_data.beam +0 -0
  107. data/lib/erlang/messenger/lib/eunit/ebin/eunit_lib.beam +0 -0
  108. data/lib/erlang/messenger/lib/eunit/ebin/eunit_proc.beam +0 -0
  109. data/lib/erlang/messenger/lib/eunit/ebin/eunit_serial.beam +0 -0
  110. data/lib/erlang/messenger/lib/eunit/ebin/eunit_server.beam +0 -0
  111. data/lib/erlang/messenger/lib/eunit/ebin/eunit_striptests.beam +0 -0
  112. data/lib/erlang/messenger/lib/eunit/ebin/eunit_test.beam +0 -0
  113. data/lib/erlang/messenger/lib/eunit/ebin/eunit_tests.beam +0 -0
  114. data/lib/erlang/messenger/lib/eunit/ebin/eunit_tty.beam +0 -0
  115. data/lib/erlang/messenger/lib/eunit/ebin/file_monitor.beam +0 -0
  116. data/lib/erlang/messenger/lib/eunit/examples/eunit_examples.erl +339 -0
  117. data/lib/erlang/messenger/lib/eunit/examples/fib.erl +19 -0
  118. data/lib/erlang/messenger/lib/eunit/examples/tests.txt +1 -0
  119. data/lib/erlang/messenger/lib/eunit/include/eunit.hrl +313 -0
  120. data/lib/erlang/messenger/lib/eunit/src/Makefile +46 -0
  121. data/lib/erlang/messenger/lib/eunit/src/autoload.erl +388 -0
  122. data/lib/erlang/messenger/lib/eunit/src/code_monitor.erl +243 -0
  123. data/lib/erlang/messenger/lib/eunit/src/eunit.app.src +21 -0
  124. data/lib/erlang/messenger/lib/eunit/src/eunit.appup.src +1 -0
  125. data/lib/erlang/messenger/lib/eunit/src/eunit.erl +196 -0
  126. data/lib/erlang/messenger/lib/eunit/src/eunit_autoexport.erl +102 -0
  127. data/lib/erlang/messenger/lib/eunit/src/eunit_data.erl +798 -0
  128. data/lib/erlang/messenger/lib/eunit/src/eunit_internal.hrl +48 -0
  129. data/lib/erlang/messenger/lib/eunit/src/eunit_lib.erl +682 -0
  130. data/lib/erlang/messenger/lib/eunit/src/eunit_proc.erl +552 -0
  131. data/lib/erlang/messenger/lib/eunit/src/eunit_serial.erl +157 -0
  132. data/lib/erlang/messenger/lib/eunit/src/eunit_server.erl +340 -0
  133. data/lib/erlang/messenger/lib/eunit/src/eunit_striptests.erl +64 -0
  134. data/lib/erlang/messenger/lib/eunit/src/eunit_test.erl +334 -0
  135. data/lib/erlang/messenger/lib/eunit/src/eunit_tests.erl +45 -0
  136. data/lib/erlang/messenger/lib/eunit/src/eunit_tty.erl +272 -0
  137. data/lib/erlang/messenger/lib/eunit/src/file_monitor.erl +409 -0
  138. data/lib/erlang/messenger/lib/eunit/sys.config +9 -0
  139. data/lib/erlang/messenger/lib/eunit/vsn.mk +1 -0
  140. data/lib/erlang/messenger/pm_client_rel-0.1.boot +0 -0
  141. data/lib/erlang/messenger/pm_client_rel-0.1.script +238 -0
  142. data/lib/erlang/messenger/pm_master_rel-0.1.boot +0 -0
  143. data/lib/erlang/messenger/pm_master_rel-0.1.script +239 -0
  144. data/lib/erlang/messenger/pm_node_rel-0.1.boot +0 -0
  145. data/lib/erlang/messenger/pm_node_rel-0.1.script +237 -0
  146. data/lib/erlang/messenger/src/client_app.erl +39 -0
  147. data/lib/erlang/messenger/src/client_server.erl +60 -0
  148. data/lib/erlang/messenger/src/master_app.erl +39 -0
  149. data/lib/erlang/messenger/src/node_app.erl +39 -0
  150. data/lib/erlang/messenger/src/pm_client.erl +49 -0
  151. data/lib/erlang/messenger/src/pm_client_supervisor.erl +38 -0
  152. data/lib/erlang/messenger/src/pm_cluster.erl +61 -0
  153. data/lib/erlang/messenger/src/pm_event_manager.erl +27 -0
  154. data/lib/erlang/messenger/src/pm_master.erl +215 -0
  155. data/lib/erlang/messenger/src/pm_master_event_handler.erl +72 -0
  156. data/lib/erlang/messenger/src/pm_master_supervisor.erl +39 -0
  157. data/lib/erlang/messenger/src/pm_node.erl +200 -0
  158. data/lib/erlang/messenger/src/pm_node_supervisor.erl +38 -0
  159. data/lib/erlang/messenger/src/pm_packager.erl +76 -0
  160. data/lib/erlang/messenger/src/pm_spawner.erl +213 -0
  161. data/lib/erlang/messenger/src/pm_strings.erl +11 -0
  162. data/lib/erlang/messenger/src/utils.erl +72 -0
  163. data/lib/erlang/messenger/useful_snippets +17 -0
  164. data/lib/poolparty/aska/aska.rb +152 -0
  165. data/lib/poolparty/base_packages/bind.rb +11 -0
  166. data/lib/poolparty/base_packages/haproxy.rb +46 -0
  167. data/lib/poolparty/base_packages/heartbeat.rb +58 -0
  168. data/lib/poolparty/base_packages/poolparty.rb +14 -0
  169. data/lib/poolparty/base_packages/ruby.rb +42 -0
  170. data/lib/poolparty/base_packages/runit.rb +21 -0
  171. data/lib/poolparty/capistrano/cloud_tasks.rb +10 -0
  172. data/lib/poolparty/capistrano.rb +54 -0
  173. data/lib/poolparty/config/postlaunchmessage.txt +5 -0
  174. data/lib/poolparty/core/array.rb +36 -0
  175. data/lib/poolparty/core/class.rb +26 -0
  176. data/lib/poolparty/core/exception.rb +10 -0
  177. data/lib/poolparty/core/float.rb +13 -0
  178. data/lib/poolparty/core/hash.rb +71 -0
  179. data/lib/poolparty/core/kernel.rb +66 -0
  180. data/lib/poolparty/core/metaid.rb +15 -0
  181. data/lib/poolparty/core/module.rb +40 -0
  182. data/lib/poolparty/core/my_open_struct.rb +18 -0
  183. data/lib/poolparty/core/object.rb +93 -0
  184. data/lib/poolparty/core/ordered_hash.rb +99 -0
  185. data/lib/poolparty/core/proc.rb +7 -0
  186. data/lib/poolparty/core/string.rb +140 -0
  187. data/lib/poolparty/core/symbol.rb +17 -0
  188. data/lib/poolparty/core/time.rb +56 -0
  189. data/lib/poolparty/dependencies.rb +49 -0
  190. data/lib/poolparty/dependency_resolver/chef_resolver.rb +221 -0
  191. data/lib/poolparty/dependency_resolver/dependency_resolver.rb +42 -0
  192. data/lib/poolparty/dependency_resolver/dependency_resolver_cloud_extensions.rb +28 -0
  193. data/lib/poolparty/dependency_resolver/puppet.rb +75 -0
  194. data/lib/poolparty/dependency_resolver/puppet_resolver.rb +173 -0
  195. data/lib/poolparty/exceptions/CloudNotFoundException.rb +7 -0
  196. data/lib/poolparty/exceptions/LoadRulesException.rb +7 -0
  197. data/lib/poolparty/exceptions/MasterException.rb +10 -0
  198. data/lib/poolparty/exceptions/ProvisionerException.rb +5 -0
  199. data/lib/poolparty/exceptions/RemoteException.rb +12 -0
  200. data/lib/poolparty/exceptions/ResourceException.rb +7 -0
  201. data/lib/poolparty/exceptions/RuntimeException.rb +7 -0
  202. data/lib/poolparty/exceptions/SpecException.rb +7 -0
  203. data/lib/poolparty/exceptions/TemplateNotFound.rb +7 -0
  204. data/lib/poolparty/exceptions/UnacceptableCommand.rb +5 -0
  205. data/lib/poolparty/exceptions/dependency_resolver_exception.rb +5 -0
  206. data/lib/poolparty/exceptions/package_exception.rb +7 -0
  207. data/lib/poolparty/extra/deployments.rb +31 -0
  208. data/lib/poolparty/helpers/binary.rb +67 -0
  209. data/lib/poolparty/helpers/console.rb +48 -0
  210. data/lib/poolparty/helpers/display.rb +30 -0
  211. data/lib/poolparty/helpers/hash_printer.rb +44 -0
  212. data/lib/poolparty/helpers/loading.rb +4 -0
  213. data/lib/poolparty/helpers/nice_printer.rb +36 -0
  214. data/lib/poolparty/helpers/optioner.rb +149 -0
  215. data/lib/poolparty/helpers/ruberl.rb +33 -0
  216. data/lib/poolparty/lite.rb +20 -0
  217. data/lib/poolparty/modules/cloud_dsl.rb +20 -0
  218. data/lib/poolparty/modules/cloud_resourcer.rb +122 -0
  219. data/lib/poolparty/modules/daemonizable.rb +141 -0
  220. data/lib/poolparty/modules/definable_resource.rb +57 -0
  221. data/lib/poolparty/modules/file_writer.rb +95 -0
  222. data/lib/poolparty/modules/output.rb +13 -0
  223. data/lib/poolparty/modules/pretty_printer.rb +40 -0
  224. data/lib/poolparty/modules/resourcing_dsl.rb +74 -0
  225. data/lib/poolparty/modules/s3_string.rb +32 -0
  226. data/lib/poolparty/modules/safe_instance.rb +31 -0
  227. data/lib/poolparty/modules/thread_pool.rb +106 -0
  228. data/lib/poolparty/monitors/base_monitor.rb +81 -0
  229. data/lib/poolparty/monitors/monitor_rack.rb +132 -0
  230. data/lib/poolparty/monitors/monitors/load_monitor.rb +15 -0
  231. data/lib/poolparty/monitors/monitors/memory_monitor.rb +50 -0
  232. data/lib/poolparty/monitors/monitors/server_monitor.rb +7 -0
  233. data/lib/poolparty/monitors/monitors/web_monitor.rb +18 -0
  234. data/lib/poolparty/monitors/neighborhood_monitor.rb +25 -0
  235. data/lib/poolparty/monitors/stats_monitor.rb +182 -0
  236. data/lib/poolparty/monitors.rb +6 -0
  237. data/lib/poolparty/net/init.rb +11 -0
  238. data/lib/poolparty/net/messenger.rb +55 -0
  239. data/lib/poolparty/net/remote_bases.rb +21 -0
  240. data/lib/poolparty/net/remote_instance.rb +109 -0
  241. data/lib/poolparty/net/remoter/cloud_control.rb +251 -0
  242. data/lib/poolparty/net/remoter/connections.rb +180 -0
  243. data/lib/poolparty/net/remoter/interactive.rb +121 -0
  244. data/lib/poolparty/net/remoter/lists.rb +12 -0
  245. data/lib/poolparty/net/remoter_base.rb +97 -0
  246. data/lib/poolparty/net/remoter_bases/ec2/ec2.rb +235 -0
  247. data/lib/poolparty/net/remoter_bases/ec2/ec2_remote_instance.rb +53 -0
  248. data/lib/poolparty/net/remoter_bases/ec2/ec2_response_object.rb +64 -0
  249. data/lib/poolparty/plugins/chef.rb +168 -0
  250. data/lib/poolparty/plugins/deploydirectory.rb +47 -0
  251. data/lib/poolparty/plugins/git.rb +66 -0
  252. data/lib/poolparty/plugins/line_in_file.rb +13 -0
  253. data/lib/poolparty/plugins/rsyncmirror.rb +28 -0
  254. data/lib/poolparty/plugins/runit.rb +96 -0
  255. data/lib/poolparty/plugins/svn.rb +48 -0
  256. data/lib/poolparty/poolparty/cloud.rb +216 -0
  257. data/lib/poolparty/poolparty/custom_resource.rb +45 -0
  258. data/lib/poolparty/poolparty/default.rb +167 -0
  259. data/lib/poolparty/poolparty/key.rb +75 -0
  260. data/lib/poolparty/poolparty/loggable.rb +28 -0
  261. data/lib/poolparty/poolparty/neighborhoods.rb +69 -0
  262. data/lib/poolparty/poolparty/plugin.rb +69 -0
  263. data/lib/poolparty/poolparty/plugin_model.rb +45 -0
  264. data/lib/poolparty/poolparty/pool.rb +76 -0
  265. data/lib/poolparty/poolparty/poolparty_base_class.rb +181 -0
  266. data/lib/poolparty/poolparty/resource.rb +205 -0
  267. data/lib/poolparty/poolparty/script.rb +58 -0
  268. data/lib/poolparty/poolparty/service.rb +34 -0
  269. data/lib/poolparty/poolparty/template.rb +27 -0
  270. data/lib/poolparty/provision/boot_strapper.rb +141 -0
  271. data/lib/poolparty/provision/configurations/chef.rb +22 -0
  272. data/lib/poolparty/provision/configurations/puppet.rb +28 -0
  273. data/lib/poolparty/provision/dr_configure.rb +85 -0
  274. data/lib/poolparty/resources/cron.rb +14 -0
  275. data/lib/poolparty/resources/custom_service.rb +30 -0
  276. data/lib/poolparty/resources/directory.rb +13 -0
  277. data/lib/poolparty/resources/exec.rb +25 -0
  278. data/lib/poolparty/resources/file.rb +29 -0
  279. data/lib/poolparty/resources/host.rb +16 -0
  280. data/lib/poolparty/resources/mount.rb +21 -0
  281. data/lib/poolparty/resources/package.rb +12 -0
  282. data/lib/poolparty/resources/remote_file.rb +20 -0
  283. data/lib/poolparty/resources/service.rb +20 -0
  284. data/lib/poolparty/resources/sshkey.rb +27 -0
  285. data/lib/poolparty/resources/symlink.rb +21 -0
  286. data/lib/poolparty/resources/user.rb +13 -0
  287. data/lib/poolparty/resources/variable.rb +9 -0
  288. data/lib/poolparty/schema.rb +64 -0
  289. data/lib/poolparty/services/conditional.rb +46 -0
  290. data/lib/poolparty/services/gem_package.rb +52 -0
  291. data/lib/poolparty/spec/core/string.rb +18 -0
  292. data/lib/poolparty/spec/matchers/a_spec_extensions_base.rb +26 -0
  293. data/lib/poolparty/spec/matchers/have_cron.rb +28 -0
  294. data/lib/poolparty/spec/matchers/have_deploydirectory.rb +15 -0
  295. data/lib/poolparty/spec/matchers/have_directory.rb +31 -0
  296. data/lib/poolparty/spec/matchers/have_exec.rb +28 -0
  297. data/lib/poolparty/spec/matchers/have_file.rb +28 -0
  298. data/lib/poolparty/spec/matchers/have_gempackage.rb +28 -0
  299. data/lib/poolparty/spec/matchers/have_git.rb +28 -0
  300. data/lib/poolparty/spec/matchers/have_host.rb +28 -0
  301. data/lib/poolparty/spec/matchers/have_mount.rb +28 -0
  302. data/lib/poolparty/spec/matchers/have_package.rb +28 -0
  303. data/lib/poolparty/spec/matchers/have_remotefile.rb +28 -0
  304. data/lib/poolparty/spec/matchers/have_rsyncmirror.rb +28 -0
  305. data/lib/poolparty/spec/matchers/have_service.rb +28 -0
  306. data/lib/poolparty/spec/matchers/have_sshkey.rb +28 -0
  307. data/lib/poolparty/spec/matchers/have_symlink.rb +28 -0
  308. data/lib/poolparty/spec/matchers/have_variable.rb +32 -0
  309. data/lib/poolparty/spec/spec/dynamic_matchers.rb +63 -0
  310. data/lib/poolparty/spec/spec/ensure_matchers_exist.rb +7 -0
  311. data/lib/poolparty/spec/templates/have_base.rb +28 -0
  312. data/lib/poolparty/spec.rb +31 -0
  313. data/lib/poolparty/templates/authkeys +2 -0
  314. data/lib/poolparty/templates/cib.xml +54 -0
  315. data/lib/poolparty/templates/erlang_cookie_maker +6 -0
  316. data/lib/poolparty/templates/gem +27 -0
  317. data/lib/poolparty/templates/gemrc +11 -0
  318. data/lib/poolparty/templates/ha.cf +17 -0
  319. data/lib/poolparty/templates/haproxy.conf +36 -0
  320. data/lib/poolparty/templates/haresources +3 -0
  321. data/lib/poolparty/templates/logd.cf +42 -0
  322. data/lib/poolparty/templates/messenger/client/log-run.erb +2 -0
  323. data/lib/poolparty/templates/messenger/client/run.erb +4 -0
  324. data/lib/poolparty/templates/messenger/master/log-run.erb +2 -0
  325. data/lib/poolparty/templates/messenger/master/run.erb +4 -0
  326. data/lib/poolparty/templates/messenger/node/log-run.erb +2 -0
  327. data/lib/poolparty/templates/messenger/node/run.erb +4 -0
  328. data/lib/poolparty/templates/monitor.ru +16 -0
  329. data/lib/poolparty/templates/namespaceauth.conf +19 -0
  330. data/lib/poolparty/templates/poolparty.monitor +14 -0
  331. data/lib/poolparty/templates/puppet/add_puppet_to_hosts +6 -0
  332. data/lib/poolparty/templates/puppet/puppet.conf +2 -0
  333. data/lib/poolparty/templates/puppet/puppetrunner +14 -0
  334. data/lib/poolparty/templates/puppet/site.pp +4 -0
  335. data/lib/poolparty/templates/puppetrunner +14 -0
  336. data/lib/poolparty/templates/yaws.conf +19 -0
  337. data/lib/poolparty/version.rb +15 -0
  338. data/lib/poolparty.rb +148 -0
  339. data/lib/poolpartycl.rb +7 -0
  340. data/script/destroy +14 -0
  341. data/script/generate +14 -0
  342. data/spec/bin/bin_spec_helper.rb +7 -0
  343. data/spec/bin/fixtures/bin_cloud_for_test.rb +19 -0
  344. data/spec/bin/server-list-active_spec.rb +22 -0
  345. data/spec/poolparty/aska/aska_spec.rb +117 -0
  346. data/spec/poolparty/base_packages/haproxy_spec.rb +7 -0
  347. data/spec/poolparty/base_packages/heartbeat_spec.rb +7 -0
  348. data/spec/poolparty/bin/console_spec.rb +83 -0
  349. data/spec/poolparty/core/array_spec.rb +46 -0
  350. data/spec/poolparty/core/float.rb +13 -0
  351. data/spec/poolparty/core/hash_spec.rb +83 -0
  352. data/spec/poolparty/core/kernel_spec.rb +24 -0
  353. data/spec/poolparty/core/module_spec.rb +15 -0
  354. data/spec/poolparty/core/object_spec.rb +68 -0
  355. data/spec/poolparty/core/ordered_hash_spec.rb +48 -0
  356. data/spec/poolparty/core/string_spec.rb +145 -0
  357. data/spec/poolparty/core/time_spec.rb +49 -0
  358. data/spec/poolparty/dependencies_spec.rb +11 -0
  359. data/spec/poolparty/dependency_resolver/chef_resolver_spec.rb +119 -0
  360. data/spec/poolparty/dependency_resolver/dependency_resolver_cloud_extensions_spec.rb +128 -0
  361. data/spec/poolparty/dependency_resolver/dependency_resolver_spec.rb +16 -0
  362. data/spec/poolparty/dependency_resolver/puppet_resolver_spec.rb +124 -0
  363. data/spec/poolparty/extra/deployments_spec.rb +68 -0
  364. data/spec/poolparty/fixtures/clouds.json +128 -0
  365. data/spec/poolparty/fixtures/test_template.erb +1 -0
  366. data/spec/poolparty/helpers/binary_spec.rb +26 -0
  367. data/spec/poolparty/helpers/display_spec.rb +13 -0
  368. data/spec/poolparty/helpers/hash_printer_spec.rb +34 -0
  369. data/spec/poolparty/helpers/optioner_spec.rb +50 -0
  370. data/spec/poolparty/id_rsa +27 -0
  371. data/spec/poolparty/modules/cloud_resourcer_spec.rb +67 -0
  372. data/spec/poolparty/modules/definable_resource.rb +9 -0
  373. data/spec/poolparty/modules/file_writer_spec.rb +64 -0
  374. data/spec/poolparty/modules/s3_string_spec.rb +15 -0
  375. data/spec/poolparty/monitors/base_monitor_spec.rb +112 -0
  376. data/spec/poolparty/monitors/monitors/cpu_monitor_spec.rb +18 -0
  377. data/spec/poolparty/monitors/monitors/memory_monitor_spec.rb +48 -0
  378. data/spec/poolparty/net/messenger_spec.rb +16 -0
  379. data/spec/poolparty/net/remote_instance_spec.rb +17 -0
  380. data/spec/poolparty/net/remote_spec.rb +286 -0
  381. data/spec/poolparty/net/remoter_base_spec.rb +35 -0
  382. data/spec/poolparty/net/remoter_bases/ec2_mocks_and_stubs.rb +24 -0
  383. data/spec/poolparty/net/remoter_bases/ec2_remote_instance_spec.rb +125 -0
  384. data/spec/poolparty/net/remoter_bases/ec2_spec.rb +119 -0
  385. data/spec/poolparty/net/remoter_spec.rb +130 -0
  386. data/spec/poolparty/plugins/chef_spec.rb +7 -0
  387. data/spec/poolparty/plugins/deploydirectory_spec.rb +51 -0
  388. data/spec/poolparty/plugins/git_spec.rb +40 -0
  389. data/spec/poolparty/plugins/line_spec.rb +22 -0
  390. data/spec/poolparty/plugins/svn_spec.rb +16 -0
  391. data/spec/poolparty/poolparty/cloud_spec.rb +345 -0
  392. data/spec/poolparty/poolparty/configurers/files/ruby_basic.rb +16 -0
  393. data/spec/poolparty/poolparty/configurers/files/ruby_plugins.rb +16 -0
  394. data/spec/poolparty/poolparty/configurers/ruby_spec.rb +42 -0
  395. data/spec/poolparty/poolparty/custom_resource_spec.rb +79 -0
  396. data/spec/poolparty/poolparty/default_spec.rb +139 -0
  397. data/spec/poolparty/poolparty/example_spec.rb +60 -0
  398. data/spec/poolparty/poolparty/key_spec.rb +42 -0
  399. data/spec/poolparty/poolparty/neighborhoods_spec.rb +66 -0
  400. data/spec/poolparty/poolparty/plugin_model_spec.rb +54 -0
  401. data/spec/poolparty/poolparty/plugin_spec.rb +41 -0
  402. data/spec/poolparty/poolparty/pool_spec.rb +100 -0
  403. data/spec/poolparty/poolparty/resource_spec.rb +209 -0
  404. data/spec/poolparty/poolparty/script_spec.rb +49 -0
  405. data/spec/poolparty/poolparty/service_spec.rb +5 -0
  406. data/spec/poolparty/poolparty/template_spec.rb +26 -0
  407. data/spec/poolparty/poolparty/test_plugins/sshkey_test +2 -0
  408. data/spec/poolparty/poolparty/test_plugins/virtual_host_template.erb +0 -0
  409. data/spec/poolparty/poolparty/test_plugins/webserver.rb +30 -0
  410. data/spec/poolparty/poolparty_base_class_spec.rb +80 -0
  411. data/spec/poolparty/poolparty_spec.rb +36 -0
  412. data/spec/poolparty/resources/cron_spec.rb +44 -0
  413. data/spec/poolparty/resources/directory_spec.rb +40 -0
  414. data/spec/poolparty/resources/exec_spec.rb +37 -0
  415. data/spec/poolparty/resources/file_spec.rb +63 -0
  416. data/spec/poolparty/resources/gem_spec.rb +7 -0
  417. data/spec/poolparty/resources/host_spec.rb +35 -0
  418. data/spec/poolparty/resources/package_spec.rb +29 -0
  419. data/spec/poolparty/resources/service_spec.rb +29 -0
  420. data/spec/poolparty/resources/sshkey_spec.rb +40 -0
  421. data/spec/poolparty/resources/symlink_spec.rb +29 -0
  422. data/spec/poolparty/resources/user_spec.rb +48 -0
  423. data/spec/poolparty/resources/variable_spec.rb +26 -0
  424. data/spec/poolparty/schema_spec.rb +53 -0
  425. data/spec/poolparty/services/conditional_spec.rb +52 -0
  426. data/spec/poolparty/spec/core/string_spec.rb +57 -0
  427. data/spec/poolparty/spec_helper.rb +263 -0
  428. data/spec/poolparty/test_spec_helper.rb +13 -0
  429. data/tasks/cloud.rake +3 -0
  430. data/tasks/development.rake +82 -0
  431. data/tasks/ec2.rake +13 -0
  432. data/tasks/environment.rake +7 -0
  433. data/tasks/instance.rake +2 -0
  434. data/tasks/poolparty.rake +54 -0
  435. data/tasks/server.rake +44 -0
  436. data/tasks/spec.rake +16 -0
  437. data/test/fixtures/test_template.erb +1 -0
  438. data/test/poolparty/core/hash_test.rb +23 -0
  439. data/test/poolparty/poolparty/template_test.rb +31 -0
  440. data/test/poolparty/provision/boot_strapper_test.rb +6 -0
  441. data/test/poolparty/provision/dr_configure_test.rb +6 -0
  442. data/test/test_generator_helper.rb +29 -0
  443. data/test/test_helper.rb +5 -0
  444. data/test/test_pool_spec_generator.rb +47 -0
  445. data/test/test_poolparty.rb +11 -0
  446. data/vendor/gems/butterfly/History.txt +4 -0
  447. data/vendor/gems/butterfly/PostInstall.txt +2 -0
  448. data/vendor/gems/butterfly/README.rdoc +48 -0
  449. data/vendor/gems/butterfly/Rakefile +62 -0
  450. data/vendor/gems/butterfly/VERSION.yml +4 -0
  451. data/vendor/gems/butterfly/bin/flutter +4 -0
  452. data/vendor/gems/butterfly/butterfly.gemspec +37 -0
  453. data/vendor/gems/butterfly/examples/config.ru +15 -0
  454. data/vendor/gems/butterfly/examples/my_app.rb +12 -0
  455. data/vendor/gems/butterfly/lib/butterfly.rb +14 -0
  456. data/vendor/gems/butterfly/lib/handler.rb +48 -0
  457. data/vendor/gems/butterfly/lib/request.rb +29 -0
  458. data/vendor/gems/butterfly/lib/response.rb +49 -0
  459. data/vendor/gems/butterfly/script/console +10 -0
  460. data/vendor/gems/butterfly/script/destroy +14 -0
  461. data/vendor/gems/butterfly/script/generate +14 -0
  462. data/vendor/gems/butterfly/test/test_adapter_base.rb +23 -0
  463. data/vendor/gems/butterfly/test/test_butterfly_request.rb +46 -0
  464. data/vendor/gems/butterfly/test/test_butterfly_response.rb +43 -0
  465. data/vendor/gems/butterfly/test/test_butterfly_server.rb +16 -0
  466. data/vendor/gems/butterfly/test/test_default.rb +12 -0
  467. data/vendor/gems/butterfly/test/test_helper.rb +6 -0
  468. data/vendor/gems/dslify/History.txt +4 -0
  469. data/vendor/gems/dslify/Manifest.txt +25 -0
  470. data/vendor/gems/dslify/PostInstall.txt +5 -0
  471. data/vendor/gems/dslify/README.txt +60 -0
  472. data/vendor/gems/dslify/Rakefile +56 -0
  473. data/vendor/gems/dslify/config/hoe.rb +73 -0
  474. data/vendor/gems/dslify/config/requirements.rb +15 -0
  475. data/vendor/gems/dslify/dslify.gemspec +40 -0
  476. data/vendor/gems/dslify/lib/dslify/dslify.rb +69 -0
  477. data/vendor/gems/dslify/lib/dslify/version.rb +10 -0
  478. data/vendor/gems/dslify/lib/dslify.rb +7 -0
  479. data/vendor/gems/dslify/script/console +10 -0
  480. data/vendor/gems/dslify/script/destroy +14 -0
  481. data/vendor/gems/dslify/script/generate +14 -0
  482. data/vendor/gems/dslify/script/txt2html +82 -0
  483. data/vendor/gems/dslify/setup.rb +1585 -0
  484. data/vendor/gems/dslify/tasks/deployment.rake +34 -0
  485. data/vendor/gems/dslify/tasks/environment.rake +7 -0
  486. data/vendor/gems/dslify/tasks/website.rake +17 -0
  487. data/vendor/gems/dslify/test/test_dslify.rb +114 -0
  488. data/vendor/gems/dslify/website/index.html +86 -0
  489. data/vendor/gems/dslify/website/index.txt +83 -0
  490. data/vendor/gems/dslify/website/javascripts/rounded_corners_lite.inc.js +285 -0
  491. data/vendor/gems/dslify/website/stylesheets/screen.css +138 -0
  492. data/vendor/gems/dslify/website/template.html.erb +48 -0
  493. data/vendor/gems/parenting/History.txt +4 -0
  494. data/vendor/gems/parenting/Manifest.txt +13 -0
  495. data/vendor/gems/parenting/PostInstall.txt +2 -0
  496. data/vendor/gems/parenting/README.rdoc +47 -0
  497. data/vendor/gems/parenting/Rakefile +28 -0
  498. data/vendor/gems/parenting/lib/parenting/base.rb +65 -0
  499. data/vendor/gems/parenting/lib/parenting.rb +10 -0
  500. data/vendor/gems/parenting/parenting.gemspec +39 -0
  501. data/vendor/gems/parenting/script/console +10 -0
  502. data/vendor/gems/parenting/script/destroy +14 -0
  503. data/vendor/gems/parenting/script/generate +14 -0
  504. data/vendor/gems/parenting/test/file_to_eval.rb +9 -0
  505. data/vendor/gems/parenting/test/test_helper.rb +5 -0
  506. data/vendor/gems/parenting/test/test_parenting.rb +89 -0
  507. data/vendor/gems/suitcase/LICENSE +20 -0
  508. data/vendor/gems/suitcase/README.rdoc +31 -0
  509. data/vendor/gems/suitcase/Rakefile +57 -0
  510. data/vendor/gems/suitcase/VERSION.yml +4 -0
  511. data/vendor/gems/suitcase/lib/suitcase/unzipper.rb +15 -0
  512. data/vendor/gems/suitcase/lib/suitcase/zipper.rb +103 -0
  513. data/vendor/gems/suitcase/lib/suitcase.rb +5 -0
  514. data/vendor/gems/suitcase/suitcase.gemspec +52 -0
  515. data/vendor/gems/suitcase/test/suitcase_test.rb +89 -0
  516. data/vendor/gems/suitcase/test/test_dir/box.rb +1 -0
  517. data/vendor/gems/suitcase/test/test_dir/test.txt +1 -0
  518. data/vendor/gems/suitcase/test/test_helper.rb +12 -0
  519. metadata +810 -0
@@ -0,0 +1,552 @@
1
+ %% This library is free software; you can redistribute it and/or modify
2
+ %% it under the terms of the GNU Lesser General Public License as
3
+ %% published by the Free Software Foundation; either version 2 of the
4
+ %% License, or (at your option) any later version.
5
+ %%
6
+ %% This library is distributed in the hope that it will be useful, but
7
+ %% WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
+ %% Lesser General Public License for more details.
10
+ %%
11
+ %% You should have received a copy of the GNU Lesser General Public
12
+ %% License along with this library; if not, write to the Free Software
13
+ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
14
+ %% USA
15
+ %%
16
+ %% $Id: eunit_proc.erl 256 2008-09-29 17:42:21Z rcarlsson $
17
+ %%
18
+ %% @author Richard Carlsson <richardc@it.uu.se>
19
+ %% @copyright 2006 Richard Carlsson
20
+ %% @private
21
+ %% @see eunit
22
+ %% @doc Test runner process tree functions
23
+
24
+ -module(eunit_proc).
25
+
26
+ -include("eunit.hrl").
27
+ -include("eunit_internal.hrl").
28
+
29
+ -export([start/4]).
30
+
31
+
32
+ -record(procstate, {ref, id, super, insulator, parent, order}).
33
+
34
+
35
+ %% Spawns test process and returns the process Pid; sends {done,
36
+ %% Reference, Pid} to caller when finished. See the function
37
+ %% wait_for_task/2 for details about the need for the reference.
38
+ %%
39
+ %% The `Super' process receives a stream of status messages; see
40
+ %% status_message/3 for details.
41
+
42
+ start(Tests, Order, Super, Reference)
43
+ when is_pid(Super), is_reference(Reference) ->
44
+ St = #procstate{ref = Reference,
45
+ id = [],
46
+ super = Super,
47
+ order = Order},
48
+ spawn_group(local, #group{tests = Tests}, St).
49
+
50
+
51
+ %% Status messages sent to the supervisor process. (A supervisor does
52
+ %% not have to act on these messages - it can e.g. just log them, or
53
+ %% even discard them.) Each status message has the following form:
54
+ %%
55
+ %% {status, Id, Info}
56
+ %%
57
+ %% where Id identifies the item that the message pertains to, and the
58
+ %% Info part can be one of:
59
+ %%
60
+ %% {progress, 'begin', test | group}
61
+ %% indicates that the item has been entered, and what type it is
62
+ %%
63
+ %% {progress, 'end', {Status, Time::integer(), Output::io_list()}}
64
+ %% Status = 'ok' | {error, Exception} | {skipped, Cause}
65
+ %%
66
+ %% where Time is measured in milliseconds and Output is the data
67
+ %% written to the standard output stream during the test; if
68
+ %% Status is {skipped, Cause}, then Cause is a term thrown from
69
+ %% eunit_test:run_testfun/1
70
+ %%
71
+ %% {cancel, Descriptor}
72
+ %% where Descriptor can be:
73
+ %% timeout a timeout occurred
74
+ %% {blame, Id} forced to terminate because of item `Id'
75
+ %% {abort, Cause} the test failed to execute
76
+ %% {exit, Reason} the test process terminated unexpectedly
77
+ %% {startup, Reason} failed to start a remote test process
78
+ %%
79
+ %% where Cause is a term thrown from eunit_data:enter_context/4 or
80
+ %% from eunit_data:iter_next/2, and Reason is an exit term from a
81
+ %% crashed process
82
+ %%
83
+ %% Note that due to concurrent (and possibly distributed) execution,
84
+ %% there are *no* strict ordering guarantees on the status messages,
85
+ %% with one exception: a 'begin' message will always arrive before its
86
+ %% corresponding 'end' message.
87
+
88
+ status_message(Id, Info, St) ->
89
+ St#procstate.super ! {status, Id, Info}.
90
+
91
+
92
+ %% @TODO implement synchronized mode for insulator/child execution
93
+
94
+ %% Ideas for synchronized mode:
95
+ %%
96
+ %% * At each "program point", i.e., before entering a test, entering a
97
+ %% group, or leaving a group, the child will synchronize with the
98
+ %% insulator to make sure it is ok to proceed.
99
+ %%
100
+ %% * The insulator can receive controlling messages from higher up in
101
+ %% the hierarchy, telling it to pause, resume, single-step, repeat, etc.
102
+ %%
103
+ %% * Synchronization on entering/leaving groups is necessary in order to
104
+ %% get control over things such as subprocess creation/termination and
105
+ %% setup/cleanup, making it possible to, e.g., repeat all the tests
106
+ %% within a particular subprocess without terminating and restarting it,
107
+ %% or repeating tests without repeating the setup/cleanup.
108
+ %%
109
+ %% * Some tests that depend on state will not be possible to repeat, but
110
+ %% require a fresh context setup. There is nothing that can be done
111
+ %% about this, and the many tests that are repeatable should not be
112
+ %% punished because of it. The user must decide which level to restart.
113
+ %%
114
+ %% * Question: How propagate control messages down the hierarchy
115
+ %% (preferably only to the correct insulator process)? An insulator does
116
+ %% not currenctly know whether its child process has spawned subtasks.
117
+ %% (The "supervisor" process does not know the Pids of the controlling
118
+ %% insulator processes in the tree, and it probably should not be
119
+ %% responsible for this anyway.)
120
+
121
+
122
+ %% ---------------------------------------------------------------------
123
+ %% Process tree primitives
124
+
125
+ %% A "task" consists of an insulator process and a child process which
126
+ %% handles the actual work. When the child terminates, the insulator
127
+ %% process sends {done, Reference, self()} to the process which started
128
+ %% the task (the "parent"). The child process is given a State record
129
+ %% which contains the process id:s of the parent, the insulator, and the
130
+ %% supervisor.
131
+
132
+ %% @spec (Type, (#procstate{}) -> () -> term(), #procstate{}) -> pid()
133
+ %% Type = local | {remote, Node::atom()}
134
+
135
+ start_task(Type, Fun, St0) ->
136
+ St = St0#procstate{parent = self()},
137
+ %% (note: the link here is mainly to propagate signals *downwards*,
138
+ %% so that the insulator can detect if the process that started the
139
+ %% task dies before the task is done)
140
+ F = fun () -> insulator_process(Type, Fun, St) end,
141
+ case Type of
142
+ local ->
143
+ %% we assume (at least for now) that local spawns can never
144
+ %% fail in such a way that the process does not start, so a
145
+ %% new local insulator does not need to synchronize here
146
+ spawn_link(F);
147
+ {remote, Node} ->
148
+ Pid = spawn_link(Node, F),
149
+ %% See below for the need for the {ok, Reference, Pid}
150
+ %% message.
151
+ Reference = St#procstate.ref,
152
+ Monitor = erlang:monitor(process, Pid),
153
+ %% (the DOWN message is guaranteed to arrive after any
154
+ %% messages sent by the process itself)
155
+ receive
156
+ {ok, Reference, Pid} ->
157
+ Pid;
158
+ {'DOWN', Monitor, process, Pid, Reason} ->
159
+ %% send messages as if the insulator process was
160
+ %% started, but terminated on its own accord
161
+ Msg = {startup, Reason},
162
+ status_message(St#procstate.id, {cancel, Msg}, St),
163
+ self() ! {done, Reference, Pid}
164
+ end,
165
+ erlang:demonitor(Monitor, [flush]),
166
+ Pid
167
+ end.
168
+
169
+ %% Relatively simple, and hopefully failure-proof insulator process
170
+ %% (This is cleaner than temporarily setting up the caller to trap
171
+ %% signals, and does not affect the caller's mailbox or other state.)
172
+ %%
173
+ %% We assume that nobody does a 'kill' on an insulator process - if that
174
+ %% should happen, the test framework will hang since the insulator will
175
+ %% never send a reply; see below for more.
176
+ %%
177
+ %% Note that even if the insulator process itself never fails, it is
178
+ %% still possible that it does not start properly, if it is spawned
179
+ %% remotely (e.g., if the remote node is down). Therefore, remote
180
+ %% insulators must always immediately send an {ok, Reference, self()}
181
+ %% message to the parent as soon as it is spawned.
182
+
183
+ %% @spec (Type, Fun::() -> term(), St::#procstate{}) -> ok
184
+ %% Type = local | {remote, Node::atom()}
185
+
186
+ insulator_process(Type, Fun, St0) ->
187
+ process_flag(trap_exit, true),
188
+ Parent = St0#procstate.parent,
189
+ if Type == local -> ok;
190
+ true -> Parent ! {ok, St0#procstate.ref, self()}
191
+ end,
192
+ St = St0#procstate{insulator = self()},
193
+ Child = spawn_link(fun () -> child_process(Fun(St), St) end),
194
+ insulator_wait(Child, Parent, [], St).
195
+
196
+ %% Normally, child processes exit with the reason 'normal' even if the
197
+ %% executed tests failed (by throwing exceptions), since the tests are
198
+ %% executed within a try-block. Child processes can terminate abnormally
199
+ %% by the following reasons:
200
+ %% 1) an error in the processing of the test descriptors (a malformed
201
+ %% descriptor, failure in a setup, cleanup or initialization, a
202
+ %% missing module or function, or a failing generator function);
203
+ %% 2) an internal error in the test running framework itself;
204
+ %% 3) receiving a non-trapped error signal as a consequence of running
205
+ %% test code.
206
+ %% Those under point 1 are "expected errors", handled specially in the
207
+ %% protocol, while the other two are unexpected errors. (Since alt. 3
208
+ %% implies that the test neither reported success nor failure, it can
209
+ %% never be considered "proper" behaviour of a test.) Abnormal
210
+ %% termination is reported to the supervisor process but otherwise does
211
+ %% not affect the insulator compared to normal termination. Child
212
+ %% processes can also be killed abruptly by their insulators, in case of
213
+ %% a timeout or if a parent process dies.
214
+ %%
215
+ %% The insulator is the group leader for the child process, and gets all
216
+ %% of its standard I/O. The output is buffered and associated with the
217
+ %% currently active test or group, and is sent along with the 'end'
218
+ %% progress message when the test or group has finished.
219
+
220
+ insulator_wait(Child, Parent, Buf, St) ->
221
+ receive
222
+ {io_request, From, ReplyAs, Req} when is_pid(From) ->
223
+ Buf1 = io_request(From, ReplyAs, Req, hd(Buf)),
224
+ insulator_wait(Child, Parent, [Buf1 | tl(Buf)], St);
225
+ {progress, Child, Id, 'begin', Class} ->
226
+ status_message(Id, {progress, 'begin', Class}, St),
227
+ insulator_wait(Child, Parent, [[] | Buf], St);
228
+ {progress, Child, Id, 'end', {Status, Time}} ->
229
+ Msg = {Status, Time, lists:reverse(hd(Buf))},
230
+ status_message(Id, {progress, 'end', Msg}, St),
231
+ insulator_wait(Child, Parent, tl(Buf), St);
232
+ {cancel, Child, Id, Reason} ->
233
+ status_message(Id, {cancel, Reason}, St),
234
+ insulator_wait(Child, Parent, Buf, St);
235
+ {abort, Child, Id, Cause} ->
236
+ exit_messages(Id, {abort, Cause}, St),
237
+ %% no need to wait for the {'EXIT',Child,_} message
238
+ terminate_insulator(St);
239
+ {timeout, Child, Id} ->
240
+ exit_messages(Id, timeout, St),
241
+ kill_task(Child, St);
242
+ {'EXIT', Child, normal} ->
243
+ terminate_insulator(St);
244
+ {'EXIT', Child, Reason} ->
245
+ exit_messages(St#procstate.id, {exit, Reason}, St),
246
+ terminate_insulator(St);
247
+ {'EXIT', Parent, _} ->
248
+ %% make sure child processes are cleaned up recursively
249
+ kill_task(Child, St)
250
+ end.
251
+
252
+ kill_task(Child, St) ->
253
+ exit(Child, kill),
254
+ terminate_insulator(St).
255
+
256
+ %% Unlinking before exit avoids polluting the parent process with exit
257
+ %% signals from the insulator. The child process is already dead here.
258
+
259
+ terminate_insulator(St) ->
260
+ %% messaging/unlinking is ok even if the parent is already dead
261
+ Parent = St#procstate.parent,
262
+ Parent ! {done, St#procstate.ref, self()},
263
+ unlink(Parent),
264
+ exit(normal).
265
+
266
+ %% send cancel messages for the Id of the "causing" item, and also for
267
+ %% the Id of the insulator itself, if they are different
268
+ exit_messages(Id, Cause, St) ->
269
+ %% the message for the most specific Id is always sent first
270
+ status_message(Id, {cancel, Cause}, St),
271
+ case St#procstate.id of
272
+ Id -> ok;
273
+ Id1 -> status_message(Id1, {cancel, {blame, Id}}, St)
274
+ end.
275
+
276
+ %% Child processes send all messages via the insulator to ensure proper
277
+ %% sequencing with timeouts and exit signals.
278
+
279
+ abort_message(Cause, St) ->
280
+ St#procstate.insulator ! {abort, self(), St#procstate.id, Cause}.
281
+
282
+ cancel_message(Msg, St) ->
283
+ St#procstate.insulator ! {cancel, self(), St#procstate.id, Msg}.
284
+
285
+ progress_message(Type, Data, St) ->
286
+ St#procstate.insulator ! {progress, self(), St#procstate.id,
287
+ Type, Data}.
288
+
289
+ %% Timeout handling
290
+
291
+ set_timeout(Time, St) ->
292
+ erlang:send_after(Time, St#procstate.insulator,
293
+ {timeout, self(), St#procstate.id}).
294
+
295
+ clear_timeout(Ref) ->
296
+ erlang:cancel_timer(Ref).
297
+
298
+ with_timeout(undefined, Default, F, St) ->
299
+ with_timeout(Default, F, St);
300
+ with_timeout(Time, _Default, F, St) ->
301
+ with_timeout(Time, F, St).
302
+
303
+ with_timeout(infinity, F, _St) ->
304
+ %% don't start timers unnecessarily
305
+ {T0, _} = statistics(wall_clock),
306
+ Value = F(),
307
+ {T1, _} = statistics(wall_clock),
308
+ {Value, T1 - T0};
309
+ with_timeout(Time, F, St) when is_integer(Time), Time > 16#FFFFffff ->
310
+ with_timeout(16#FFFFffff, F, St);
311
+ with_timeout(Time, F, St) when is_integer(Time), Time < 0 ->
312
+ with_timeout(0, F, St);
313
+ with_timeout(Time, F, St) when is_integer(Time) ->
314
+ Ref = set_timeout(Time, St),
315
+ {T0, _} = statistics(wall_clock),
316
+ try F() of
317
+ Value ->
318
+ %% we could also read the timer, but this is simpler
319
+ {T1, _} = statistics(wall_clock),
320
+ {Value, T1 - T0}
321
+ after
322
+ clear_timeout(Ref)
323
+ end.
324
+
325
+ %% The normal behaviour of a child process is to trap exit signals. This
326
+ %% makes it easier to write tests that spawn off separate (linked)
327
+ %% processes and test whether they terminate as expected. The testing
328
+ %% framework is not dependent on this, however, so the test code is
329
+ %% allowed to disable signal trapping as it pleases.
330
+ %% Note that I/O is redirected to the insulator process.
331
+
332
+ %% @spec (() -> term(), #procstate{}) -> ok
333
+
334
+ child_process(Fun, St) ->
335
+ process_flag(trap_exit, true),
336
+ group_leader(St#procstate.insulator, self()),
337
+ try Fun() of
338
+ _ -> ok
339
+ catch
340
+ %% the only "normal" way for a child process to bail out is to
341
+ %% throw an {eunit_abort, Reason} exception; any other exception
342
+ %% will be reported as an unexpected termination of the test
343
+ {eunit_abort, Cause} ->
344
+ abort_message(Cause, St),
345
+ exit(aborted)
346
+ end.
347
+
348
+ %% @throws abortException()
349
+ %% @type abortException() = {abort, Cause::term()}
350
+
351
+ abort_task(Cause) ->
352
+ throw({eunit_abort, Cause}).
353
+
354
+ %% Typically, the process that executes this code is trapping signals,
355
+ %% but it might not be - it is outside of our control, since test code
356
+ %% could turn off trapping. That is why the insulator process of a task
357
+ %% must be guaranteed to always send a reply before it terminates.
358
+ %%
359
+ %% The unique reference guarantees that we don't extract any message
360
+ %% from the mailbox unless it belongs to the test framework (and not to
361
+ %% the running tests) - it is not possible to use selective receive to
362
+ %% match only messages tagged with some pid in a dynamically varying set
363
+ %% of pids. When the wait-loop terminates, no such message should remain
364
+ %% in the mailbox.
365
+
366
+ wait_for_task(Pid, St) ->
367
+ wait_for_tasks(sets:from_list([Pid]), St).
368
+
369
+ wait_for_tasks(PidSet, St) ->
370
+ case sets:size(PidSet) of
371
+ 0 ->
372
+ ok;
373
+ _ ->
374
+ %% (note that when we receive this message for some task, we
375
+ %% are guaranteed that the insulator process of the task has
376
+ %% already informed the supervisor about any anomalies)
377
+ Reference = St#procstate.ref,
378
+ receive
379
+ {done, Reference, Pid} ->
380
+ %% (if Pid is not in the set, del_element has no
381
+ %% effect, so this is always safe)
382
+ Rest = sets:del_element(Pid, PidSet),
383
+ wait_for_tasks(Rest, St)
384
+ end
385
+ end.
386
+
387
+
388
+ %% ---------------------------------------------------------------------
389
+ %% Separate testing process
390
+
391
+ tests(T, St) ->
392
+ I = eunit_data:iter_init(T, St#procstate.id),
393
+ case St#procstate.order of
394
+ inorder -> tests_inorder(I, St);
395
+ inparallel -> tests_inparallel(I, 0, St);
396
+ {inparallel, N} when is_integer(N), N >= 0 ->
397
+ tests_inparallel(I, N, St)
398
+ end.
399
+
400
+ set_id(I, St) ->
401
+ St#procstate{id = eunit_data:iter_id(I)}.
402
+
403
+ tests_inorder(I, St) ->
404
+ tests_inorder(I, 0, St).
405
+
406
+ tests_inorder(I, N, St) ->
407
+ case get_next_item(I) of
408
+ {T, I1} ->
409
+ handle_item(T, set_id(I1, St)),
410
+ tests_inorder(I1, N+1, St);
411
+ none ->
412
+ N
413
+ end.
414
+
415
+ tests_inparallel(I, K0, St) ->
416
+ tests_inparallel(I, 0, St, K0, K0, sets:new()).
417
+
418
+ tests_inparallel(I, N, St, K, K0, Children) when K =< 0, K0 > 0 ->
419
+ wait_for_tasks(Children, St),
420
+ tests_inparallel(I, N, St, K0, K0, sets:new());
421
+ tests_inparallel(I, N, St, K, K0, Children) ->
422
+ case get_next_item(I) of
423
+ {T, I1} ->
424
+ Child = spawn_item(T, set_id(I1, St)),
425
+ tests_inparallel(I1, N+1, St, K - 1, K0,
426
+ sets:add_element(Child, Children));
427
+ none ->
428
+ wait_for_tasks(Children, St),
429
+ N
430
+ end.
431
+
432
+ spawn_item(T, St0) ->
433
+ Fun = fun (St) ->
434
+ fun () -> handle_item(T, St) end
435
+ end,
436
+ %% inparallel-items are always spawned locally
437
+ start_task(local, Fun, St0).
438
+
439
+ get_next_item(I) ->
440
+ eunit_data:iter_next(I, fun abort_task/1).
441
+
442
+ handle_item(T, St) ->
443
+ case T of
444
+ #test{} -> handle_test(T, St);
445
+ #group{} -> handle_group(T, St)
446
+ end.
447
+
448
+ handle_test(T, St) ->
449
+ progress_message('begin', test, St),
450
+ {Status, Time} = with_timeout(T#test.timeout, ?DEFAULT_TEST_TIMEOUT,
451
+ fun () -> run_test(T) end, St),
452
+ progress_message('end', {Status, Time}, St),
453
+ ok.
454
+
455
+ %% @spec (#test{}) -> ok | {error, eunit_lib:exception()}
456
+ %% | {skipped, eunit_test:wrapperError()}
457
+
458
+ run_test(#test{f = F}) ->
459
+ try eunit_test:run_testfun(F) of
460
+ {ok, _Value} ->
461
+ %% just throw away the return value
462
+ ok;
463
+ {error, Exception} ->
464
+ {error, Exception}
465
+ catch
466
+ throw:WrapperError -> {skipped, WrapperError}
467
+ end.
468
+
469
+ set_group_order(#group{order = undefined}, St) ->
470
+ St;
471
+ set_group_order(#group{order = Order}, St) ->
472
+ St#procstate{order = Order}.
473
+
474
+ handle_group(T, St0) ->
475
+ St = set_group_order(T, St0),
476
+ case T#group.spawn of
477
+ undefined ->
478
+ run_group(T, St);
479
+ Type ->
480
+ Child = spawn_group(Type, T, St),
481
+ wait_for_task(Child, St)
482
+ end.
483
+
484
+ spawn_group(Type, T, St0) ->
485
+ Fun = fun (St) ->
486
+ fun () -> run_group(T, St) end
487
+ end,
488
+ start_task(Type, Fun, St0).
489
+
490
+ run_group(T, St) ->
491
+ %% note that the setup/cleanup is outside the group timeout; if the
492
+ %% setup fails, we do not start any timers
493
+ Timeout = T#group.timeout,
494
+ progress_message('begin', group, St),
495
+ F = fun (T) -> enter_group(T, Timeout, St) end,
496
+ try with_context(T, F) of
497
+ {Status, Time} ->
498
+ progress_message('end', {Status, Time}, St)
499
+ catch
500
+ throw:Cause ->
501
+ cancel_message({abort, Cause}, St)
502
+ end,
503
+ ok.
504
+
505
+ enter_group(T, Timeout, St) ->
506
+ with_timeout(Timeout, ?DEFAULT_GROUP_TIMEOUT,
507
+ fun () -> tests(T, St) end, St).
508
+
509
+ with_context(#group{context = undefined, tests = T}, F) ->
510
+ F(T);
511
+ with_context(#group{context = #context{} = C, tests = I}, F) ->
512
+ eunit_data:enter_context(C, I, F).
513
+
514
+ %% Implementation of buffering I/O for the insulator process. (Note that
515
+ %% each batch of characters is just pushed on the buffer, so it needs to
516
+ %% be reversed when it is flushed.)
517
+
518
+ io_request(From, ReplyAs, Req, Buf) ->
519
+ {Reply, Buf1} = io_request(Req, Buf),
520
+ io_reply(From, ReplyAs, Reply),
521
+ Buf1.
522
+
523
+ io_reply(From, ReplyAs, Reply) ->
524
+ From ! {io_reply, ReplyAs, Reply}.
525
+
526
+ io_request({put_chars, Chars}, Buf) ->
527
+ {ok, [Chars | Buf]};
528
+ io_request({put_chars, M, F, As}, Buf) ->
529
+ try apply(M, F, As) of
530
+ Chars -> {ok, [Chars | Buf]}
531
+ catch
532
+ C:T -> {{error, {C,T,erlang:get_stacktrace()}}, Buf}
533
+ end;
534
+ io_request({get_chars, _Prompt, _N}, Buf) ->
535
+ {eof, Buf};
536
+ io_request({get_chars, _Prompt, _M, _F, _Xs}, Buf) ->
537
+ {eof, Buf};
538
+ io_request({get_line, _Prompt}, Buf) ->
539
+ {eof, Buf};
540
+ io_request({get_until, _Prompt, _M, _F, _As}, Buf) ->
541
+ {eof, Buf};
542
+ io_request({setopts, _Opts}, Buf) ->
543
+ {ok, Buf};
544
+ io_request({requests, Reqs}, Buf) ->
545
+ io_requests(Reqs, {ok, Buf});
546
+ io_request(_, Buf) ->
547
+ {{error, request}, Buf}.
548
+
549
+ io_requests([R | Rs], {ok, Buf}) ->
550
+ io_requests(Rs, io_request(R, Buf));
551
+ io_requests(_, Result) ->
552
+ Result.
@@ -0,0 +1,157 @@
1
+ %% This library is free software; you can redistribute it and/or modify
2
+ %% it under the terms of the GNU Lesser General Public License as
3
+ %% published by the Free Software Foundation; either version 2 of the
4
+ %% License, or (at your option) any later version.
5
+ %%
6
+ %% This library is distributed in the hope that it will be useful, but
7
+ %% WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
+ %% Lesser General Public License for more details.
10
+ %%
11
+ %% You should have received a copy of the GNU Lesser General Public
12
+ %% License along with this library; if not, write to the Free Software
13
+ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
14
+ %% USA
15
+ %%
16
+ %% $Id: eunit_serial.erl 249 2008-05-11 20:06:45Z rcarlsson $
17
+ %%
18
+ %% @author Richard Carlsson <richardc@it.uu.se>
19
+ %% @copyright 2006 Richard Carlsson
20
+ %% @private
21
+ %% @see eunit
22
+ %% @doc Event serializing process which works as an adapter and
23
+ %% multiplexer for "supervisor" processes
24
+
25
+ -module(eunit_serial).
26
+
27
+ -include("eunit.hrl").
28
+ -include("eunit_internal.hrl").
29
+
30
+ -export([start/1]).
31
+
32
+ %% Notes:
33
+ %% * Due to concurrency, there are no guarantees that we will receive
34
+ %% all status messages for the items within a group before we receive
35
+ %% the 'end' message of the group itself.
36
+ %%
37
+ %% * A cancelling event may arrive at any time, and may concern items we
38
+ %% are not yet expecting (if tests are executed in parallel), or may
39
+ %% concern not only the current item but possibly a group ancestor of
40
+ %% the current item (as in the case of a group timeout).
41
+ %%
42
+ %% * It is not possible to use selective receive to extract only those
43
+ %% cancelling messages that affect the current item and its parents;
44
+ %% basically, because we cannot have a dynamically computed prefix as a
45
+ %% pattern in a receive. Hence, we must extract each cancelling event as
46
+ %% it arrives and keep track of them separately.
47
+ %%
48
+ %% * Before we wait for a new item, we must check whether it (and thus
49
+ %% also all its subitems, if any) is already cancelled.
50
+ %%
51
+ %% * When a new cancelling event arrives, we must either store it for
52
+ %% future use, and/or cancel the current item and possibly one or more
53
+ %% of its parent groups.
54
+
55
+ -record(state, {listeners,
56
+ cancelled = eunit_lib:trie_new(),
57
+ messages = dict:new()}).
58
+
59
+ start(Pids) ->
60
+ spawn(fun () -> serializer(Pids) end).
61
+
62
+ serializer(Pids) ->
63
+ St = #state{listeners = sets:from_list(Pids),
64
+ cancelled = eunit_lib:trie_new(),
65
+ messages = dict:new()},
66
+ item([], none, none, St),
67
+ exit(normal).
68
+
69
+ item(Id, ParentId, N0, St0) ->
70
+ case wait(Id, 'begin', ParentId, N0, St0) of
71
+ {none, St1} ->
72
+ {true, St1};
73
+ {{cancel, Done, undefined}, St1} ->
74
+ {Done, cast({status, Id, {cancel, undefined}}, St1)};
75
+ {{cancel, Done, Msg}, St1} ->
76
+ {Done, cast(Msg, St1)};
77
+ {{ok, Msg}, St1} ->
78
+ %%?debugVal({got_begin, Id, Msg}),
79
+ cast(Msg, St1),
80
+ St2 = case Msg of
81
+ {status, _, {progress, 'begin', group}} ->
82
+ items(Id, 0, St1);
83
+ _ -> St1
84
+ end,
85
+ case wait(Id, 'end', ParentId, N0, St2) of
86
+ {{cancel, Done, undefined}, St3} ->
87
+ {Done, cast({status, Id, {cancel, undefined}}, St3)};
88
+ {{cancel, Done, Msg1}, St3} ->
89
+ {Done, cast(Msg1, St3)};
90
+ {{ok, Msg1}, St3} ->
91
+ %%?debugVal({got_end, Id, Msg1}),
92
+ {false, cast(Msg1, St3)}
93
+ end
94
+ end.
95
+
96
+ items(ParentId, N0, St) ->
97
+ N = N0 + 1,
98
+ case item(ParentId ++ [N], ParentId, N0, St) of
99
+ {false, St1} ->
100
+ items(ParentId, N, St1);
101
+ {true, St1} ->
102
+ St1
103
+ end.
104
+
105
+ cast(M, St) ->
106
+ sets:fold(fun (L, M) -> L ! M end, M, St#state.listeners),
107
+ St.
108
+
109
+ wait(Id, Type, ParentId, N0, St) ->
110
+ %%?debugVal({wait, Id, Type}),
111
+ case check_cancelled(Id, St) of
112
+ no ->
113
+ case recall(Id, St) of
114
+ undefined ->
115
+ wait_1(Id, Type, ParentId, N0, St);
116
+ Msg ->
117
+ {{ok, Msg}, forget(Id, St)}
118
+ end;
119
+ Why ->
120
+ %%?debugVal({cancelled, Why, Id, ParentId}),
121
+ Done = (Why =:= prefix),
122
+ {{cancel, Done, recall(Id, St)}, forget(Id, St)}
123
+ end.
124
+
125
+ wait_1(Id, Type, ParentId, N0, St) ->
126
+ receive
127
+ {status, Id, {progress, Type, _}}=Msg ->
128
+ %%?debugVal({Type, ParentId, Id}),
129
+ {{ok, Msg}, St};
130
+ {status,ParentId,{progress,'end',{N0,_,_}}}=Msg ->
131
+ %%?debugVal({end_group, ParentId, Id}),
132
+ {none, remember(ParentId, Msg, St)};
133
+ {status, SomeId, {cancel, _Cause}}=Msg ->
134
+ %%?debugVal({got_cancel, SomeId, ParentId, Id}),
135
+ St1 = set_cancelled(SomeId, Msg, St),
136
+ wait(Id, Type, ParentId, N0, St1)
137
+ end.
138
+
139
+ set_cancelled(Id, Msg, St0) ->
140
+ St = remember(Id, Msg, St0),
141
+ St#state{cancelled = eunit_lib:trie_store(Id, St0#state.cancelled)}.
142
+
143
+ check_cancelled(Id, St) ->
144
+ eunit_lib:trie_match(Id, St#state.cancelled).
145
+
146
+ remember(Id, Msg, St) ->
147
+ St#state{messages = dict:store(Id, Msg, St#state.messages)}.
148
+
149
+ forget(Id, St) ->
150
+ %% this is just to enable garbage collection of old messages
151
+ St#state{messages = dict:store(Id, undefined, St#state.messages)}.
152
+
153
+ recall(Id, St) ->
154
+ case dict:find(Id, St#state.messages) of
155
+ {ok, Msg} -> Msg;
156
+ error -> undefined
157
+ end.