/lib/gemcache/ruby/1.9.1/gems/state_machine-1.1.2/test/unit/machine_collection_test.rb

https://bitbucket.org/technopunk2099/metasploit-framework · Ruby · 599 lines · 471 code · 123 blank · 5 comment · 0 complexity · 52624576247b2797a690dfd1a5c59524 MD5 · raw file

  1. require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
  2. class MachineCollectionByDefaultTest < Test::Unit::TestCase
  3. def setup
  4. @machines = StateMachine::MachineCollection.new
  5. end
  6. def test_should_not_have_any_machines
  7. assert @machines.empty?
  8. end
  9. end
  10. class MachineCollectionStateInitializationTest < Test::Unit::TestCase
  11. def setup
  12. @machines = StateMachine::MachineCollection.new
  13. @klass = Class.new
  14. @machines[:state] = StateMachine::Machine.new(@klass, :state, :initial => :parked)
  15. @machines[:alarm_state] = StateMachine::Machine.new(@klass, :alarm_state, :initial => lambda {|object| :active})
  16. @machines[:alarm_state].state :active, :value => lambda {'active'}
  17. # Prevent the auto-initialization hook from firing
  18. @klass.class_eval do
  19. def initialize
  20. end
  21. end
  22. @object = @klass.new
  23. @object.state = nil
  24. @object.alarm_state = nil
  25. end
  26. def test_should_raise_exception_if_invalid_option_specified
  27. assert_raise(ArgumentError) {@machines.initialize_states(@object, :invalid => true)}
  28. end
  29. def test_should_only_initialize_static_states_prior_to_block
  30. @machines.initialize_states(@object) do
  31. @state_in_block = @object.state
  32. @alarm_state_in_block = @object.alarm_state
  33. end
  34. assert_equal 'parked', @state_in_block
  35. assert_nil @alarm_state_in_block
  36. end
  37. def test_should_only_initialize_dynamic_states_after_block
  38. @machines.initialize_states(@object) do
  39. @alarm_state_in_block = @object.alarm_state
  40. end
  41. assert_nil @alarm_state_in_block
  42. assert_equal 'active', @object.alarm_state
  43. end
  44. def test_should_initialize_all_states_without_block
  45. @machines.initialize_states(@object)
  46. assert_equal 'parked', @object.state
  47. assert_equal 'active', @object.alarm_state
  48. end
  49. def test_should_skip_static_states_if_disabled
  50. @machines.initialize_states(@object, :static => false)
  51. assert_nil @object.state
  52. assert_equal 'active', @object.alarm_state
  53. end
  54. def test_should_initialize_existing_static_states_by_default
  55. @object.state = 'idling'
  56. @machines.initialize_states(@object)
  57. assert_equal 'parked', @object.state
  58. end
  59. def test_should_initialize_existing_static_states_if_forced
  60. @object.state = 'idling'
  61. @machines.initialize_states(@object, :static => :force)
  62. assert_equal 'parked', @object.state
  63. end
  64. def test_should_not_initialize_existing_static_states_if_not_forced
  65. @object.state = 'idling'
  66. @machines.initialize_states(@object, :static => true)
  67. assert_equal 'idling', @object.state
  68. end
  69. def test_should_skip_dynamic_states_if_disabled
  70. @machines.initialize_states(@object, :dynamic => false)
  71. assert_equal 'parked', @object.state
  72. assert_nil @object.alarm_state
  73. end
  74. def test_should_not_initialize_existing_dynamic_states_by_default
  75. @object.alarm_state = 'inactive'
  76. @machines.initialize_states(@object)
  77. assert_equal 'inactive', @object.alarm_state
  78. end
  79. def test_should_initialize_existing_dynamic_states_if_forced
  80. @object.alarm_state = 'inactive'
  81. @machines.initialize_states(@object, :dynamic => :force)
  82. assert_equal 'active', @object.alarm_state
  83. end
  84. def test_should_not_initialize_existing_dynamic_states_if_not_forced
  85. @object.alarm_state = 'inactive'
  86. @machines.initialize_states(@object, :dynamic => true)
  87. assert_equal 'inactive', @object.alarm_state
  88. end
  89. end
  90. class MachineCollectionFireTest < Test::Unit::TestCase
  91. def setup
  92. @machines = StateMachine::MachineCollection.new
  93. @klass = Class.new do
  94. attr_reader :saved
  95. def save
  96. @saved = true
  97. end
  98. end
  99. # First machine
  100. @machines[:state] = @state = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  101. @state.event :ignite do
  102. transition :parked => :idling
  103. end
  104. @state.event :park do
  105. transition :idling => :parked
  106. end
  107. # Second machine
  108. @machines[:alarm_state] = @alarm_state = StateMachine::Machine.new(@klass, :alarm_state, :initial => :active, :action => :save, :namespace => 'alarm')
  109. @alarm_state.event :enable do
  110. transition :off => :active
  111. end
  112. @alarm_state.event :disable do
  113. transition :active => :off
  114. end
  115. @object = @klass.new
  116. end
  117. def test_should_raise_exception_if_invalid_event_specified
  118. exception = assert_raise(StateMachine::InvalidEvent) { @machines.fire_events(@object, :invalid) }
  119. assert_equal :invalid, exception.event
  120. exception = assert_raise(StateMachine::InvalidEvent) { @machines.fire_events(@object, :ignite, :invalid) }
  121. assert_equal :invalid, exception.event
  122. end
  123. def test_should_fail_if_any_event_cannot_transition
  124. assert !@machines.fire_events(@object, :park, :disable_alarm)
  125. assert_equal 'parked', @object.state
  126. assert_equal 'active', @object.alarm_state
  127. assert !@object.saved
  128. assert !@machines.fire_events(@object, :ignite, :enable_alarm)
  129. assert_equal 'parked', @object.state
  130. assert_equal 'active', @object.alarm_state
  131. assert !@object.saved
  132. end
  133. def test_should_run_failure_callbacks_if_any_event_cannot_transition
  134. @machines[:state].after_failure {@state_failure_run = true}
  135. @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
  136. assert !@machines.fire_events(@object, :park, :disable_alarm)
  137. assert @state_failure_run
  138. assert !@alarm_state_failure_run
  139. end
  140. def test_should_be_successful_if_all_events_transition
  141. assert @machines.fire_events(@object, :ignite, :disable_alarm)
  142. assert_equal 'idling', @object.state
  143. assert_equal 'off', @object.alarm_state
  144. assert @object.saved
  145. end
  146. def test_should_not_save_if_skipping_action
  147. assert @machines.fire_events(@object, :ignite, :disable_alarm, false)
  148. assert_equal 'idling', @object.state
  149. assert_equal 'off', @object.alarm_state
  150. assert !@object.saved
  151. end
  152. end
  153. class MachineCollectionFireWithTransactionsTest < Test::Unit::TestCase
  154. def setup
  155. @machines = StateMachine::MachineCollection.new
  156. @klass = Class.new do
  157. attr_accessor :allow_save
  158. def save
  159. @allow_save
  160. end
  161. end
  162. StateMachine::Integrations.const_set('Custom', Module.new do
  163. include StateMachine::Integrations::Base
  164. attr_reader :rolled_back
  165. def transaction(object)
  166. @rolled_back = yield
  167. end
  168. end)
  169. # First machine
  170. @machines[:state] = @state = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save, :integration => :custom)
  171. @state.event :ignite do
  172. transition :parked => :idling
  173. end
  174. # Second machine
  175. @machines[:alarm_state] = @alarm_state = StateMachine::Machine.new(@klass, :alarm_state, :initial => :active, :action => :save, :namespace => 'alarm', :integration => :custom)
  176. @alarm_state.event :disable do
  177. transition :active => :off
  178. end
  179. @object = @klass.new
  180. end
  181. def test_should_not_rollback_if_successful
  182. @object.allow_save = true
  183. assert @machines.fire_events(@object, :ignite, :disable_alarm)
  184. assert_equal true, @state.rolled_back
  185. assert_nil @alarm_state.rolled_back
  186. assert_equal 'idling', @object.state
  187. assert_equal 'off', @object.alarm_state
  188. end
  189. def test_should_rollback_if_not_successful
  190. @object.allow_save = false
  191. assert !@machines.fire_events(@object, :ignite, :disable_alarm)
  192. assert_equal false, @state.rolled_back
  193. assert_nil @alarm_state.rolled_back
  194. assert_equal 'parked', @object.state
  195. assert_equal 'active', @object.alarm_state
  196. end
  197. def test_should_run_failure_callbacks_if_not_successful
  198. @object.allow_save = false
  199. @machines[:state].after_failure {@state_failure_run = true}
  200. @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
  201. assert !@machines.fire_events(@object, :ignite, :disable_alarm)
  202. assert @state_failure_run
  203. assert @alarm_state_failure_run
  204. end
  205. def teardown
  206. StateMachine::Integrations.send(:remove_const, 'Custom')
  207. end
  208. end
  209. class MachineCollectionFireWithValidationsTest < Test::Unit::TestCase
  210. def setup
  211. StateMachine::Integrations.const_set('Custom', Module.new do
  212. include StateMachine::Integrations::Base
  213. def invalidate(object, attribute, message, values = [])
  214. (object.errors ||= []) << generate_message(message, values)
  215. end
  216. def reset(object)
  217. object.errors = []
  218. end
  219. end)
  220. @klass = Class.new do
  221. attr_accessor :errors
  222. def initialize
  223. @errors = []
  224. super
  225. end
  226. end
  227. @machines = StateMachine::MachineCollection.new
  228. @machines[:state] = @state = StateMachine::Machine.new(@klass, :state, :initial => :parked, :integration => :custom)
  229. @state.event :ignite do
  230. transition :parked => :idling
  231. end
  232. @machines[:alarm_state] = @alarm_state = StateMachine::Machine.new(@klass, :alarm_state, :initial => :active, :namespace => 'alarm', :integration => :custom)
  233. @alarm_state.event :disable do
  234. transition :active => :off
  235. end
  236. @object = @klass.new
  237. end
  238. def test_should_not_invalidate_if_transitions_exist
  239. assert @machines.fire_events(@object, :ignite, :disable_alarm)
  240. assert_equal [], @object.errors
  241. end
  242. def test_should_invalidate_if_no_transitions_exist
  243. @object.state = 'idling'
  244. @object.alarm_state = 'off'
  245. assert !@machines.fire_events(@object, :ignite, :disable_alarm)
  246. assert_equal ['cannot transition via "ignite"', 'cannot transition via "disable"'], @object.errors
  247. end
  248. def test_should_run_failure_callbacks_if_no_transitions_exist
  249. @object.state = 'idling'
  250. @object.alarm_state = 'off'
  251. @machines[:state].after_failure {@state_failure_run = true}
  252. @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
  253. assert !@machines.fire_events(@object, :ignite, :disable_alarm)
  254. assert @state_failure_run
  255. assert @alarm_state_failure_run
  256. end
  257. def teardown
  258. StateMachine::Integrations.send(:remove_const, 'Custom')
  259. end
  260. end
  261. class MachineCollectionTransitionsWithoutEventsTest < Test::Unit::TestCase
  262. def setup
  263. @klass = Class.new
  264. @machines = StateMachine::MachineCollection.new
  265. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  266. @machine.event :ignite do
  267. transition :parked => :idling
  268. end
  269. @object = @klass.new
  270. @object.state_event = nil
  271. @transitions = @machines.transitions(@object, :save)
  272. end
  273. def test_should_be_empty
  274. assert @transitions.empty?
  275. end
  276. def test_should_perform
  277. assert_equal true, @transitions.perform
  278. end
  279. end
  280. class MachineCollectionTransitionsWithBlankEventsTest < Test::Unit::TestCase
  281. def setup
  282. @klass = Class.new
  283. @machines = StateMachine::MachineCollection.new
  284. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  285. @machine.event :ignite do
  286. transition :parked => :idling
  287. end
  288. @object = @klass.new
  289. @object.state_event = ''
  290. @transitions = @machines.transitions(@object, :save)
  291. end
  292. def test_should_be_empty
  293. assert @transitions.empty?
  294. end
  295. def test_should_perform
  296. assert_equal true, @transitions.perform
  297. end
  298. end
  299. class MachineCollectionTransitionsWithInvalidEventsTest < Test::Unit::TestCase
  300. def setup
  301. @klass = Class.new
  302. @machines = StateMachine::MachineCollection.new
  303. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  304. @machine.event :ignite do
  305. transition :parked => :idling
  306. end
  307. @object = @klass.new
  308. @object.state_event = 'invalid'
  309. @transitions = @machines.transitions(@object, :save)
  310. end
  311. def test_should_be_empty
  312. assert @transitions.empty?
  313. end
  314. def test_should_not_perform
  315. assert_equal false, @transitions.perform
  316. end
  317. end
  318. class MachineCollectionTransitionsWithoutTransitionTest < Test::Unit::TestCase
  319. def setup
  320. @klass = Class.new
  321. @machines = StateMachine::MachineCollection.new
  322. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  323. @machine.event :ignite do
  324. transition :parked => :idling
  325. end
  326. @object = @klass.new
  327. @object.state = 'idling'
  328. @object.state_event = 'ignite'
  329. @transitions = @machines.transitions(@object, :save)
  330. end
  331. def test_should_be_empty
  332. assert @transitions.empty?
  333. end
  334. def test_should_not_perform
  335. assert_equal false, @transitions.perform
  336. end
  337. end
  338. class MachineCollectionTransitionsWithTransitionTest < Test::Unit::TestCase
  339. def setup
  340. @klass = Class.new
  341. @machines = StateMachine::MachineCollection.new
  342. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  343. @machine.event :ignite do
  344. transition :parked => :idling
  345. end
  346. @object = @klass.new
  347. @object.state_event = 'ignite'
  348. @transitions = @machines.transitions(@object, :save)
  349. end
  350. def test_should_not_be_empty
  351. assert_equal 1, @transitions.length
  352. end
  353. def test_should_perform
  354. assert_equal true, @transitions.perform
  355. end
  356. end
  357. class MachineCollectionTransitionsWithSameActionsTest < Test::Unit::TestCase
  358. def setup
  359. @klass = Class.new
  360. @machines = StateMachine::MachineCollection.new
  361. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  362. @machine.event :ignite do
  363. transition :parked => :idling
  364. end
  365. @machines[:status] = @machine = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  366. @machine.event :shift_up do
  367. transition :first_gear => :second_gear
  368. end
  369. @object = @klass.new
  370. @object.state_event = 'ignite'
  371. @object.status_event = 'shift_up'
  372. @transitions = @machines.transitions(@object, :save)
  373. end
  374. def test_should_not_be_empty
  375. assert_equal 2, @transitions.length
  376. end
  377. def test_should_perform
  378. assert_equal true, @transitions.perform
  379. end
  380. end
  381. class MachineCollectionTransitionsWithDifferentActionsTest < Test::Unit::TestCase
  382. def setup
  383. @klass = Class.new
  384. @machines = StateMachine::MachineCollection.new
  385. @machines[:state] = @state = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  386. @state.event :ignite do
  387. transition :parked => :idling
  388. end
  389. @machines[:status] = @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :persist)
  390. @status.event :shift_up do
  391. transition :first_gear => :second_gear
  392. end
  393. @object = @klass.new
  394. @object.state_event = 'ignite'
  395. @object.status_event = 'shift_up'
  396. @transitions = @machines.transitions(@object, :save)
  397. end
  398. def test_should_only_select_matching_actions
  399. assert_equal 1, @transitions.length
  400. end
  401. end
  402. class MachineCollectionTransitionsWithExisitingTransitionsTest < Test::Unit::TestCase
  403. def setup
  404. @klass = Class.new
  405. @machines = StateMachine::MachineCollection.new
  406. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  407. @machine.event :ignite do
  408. transition :parked => :idling
  409. end
  410. @object = @klass.new
  411. @object.send(:state_event_transition=, StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling))
  412. @transitions = @machines.transitions(@object, :save)
  413. end
  414. def test_should_not_be_empty
  415. assert_equal 1, @transitions.length
  416. end
  417. def test_should_perform
  418. assert_equal true, @transitions.perform
  419. end
  420. end
  421. class MachineCollectionTransitionsWithCustomOptionsTest < Test::Unit::TestCase
  422. def setup
  423. @klass = Class.new
  424. @machines = StateMachine::MachineCollection.new
  425. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  426. @machine.event :ignite do
  427. transition :parked => :idling
  428. end
  429. @object = @klass.new
  430. @transitions = @machines.transitions(@object, :save, :after => false)
  431. end
  432. def test_should_use_custom_options
  433. assert @transitions.skip_after
  434. end
  435. end
  436. class MachineCollectionFireAttributesWithValidationsTest < Test::Unit::TestCase
  437. def setup
  438. @klass = Class.new do
  439. attr_accessor :errors
  440. def initialize
  441. @errors = []
  442. super
  443. end
  444. end
  445. @machines = StateMachine::MachineCollection.new
  446. @machines[:state] = @machine = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  447. @machine.event :ignite do
  448. transition :parked => :idling
  449. end
  450. class << @machine
  451. def invalidate(object, attribute, message, values = [])
  452. (object.errors ||= []) << generate_message(message, values)
  453. end
  454. def reset(object)
  455. object.errors = []
  456. end
  457. end
  458. @object = @klass.new
  459. end
  460. def test_should_invalidate_if_event_is_invalid
  461. @object.state_event = 'invalid'
  462. @machines.transitions(@object, :save)
  463. assert !@object.errors.empty?
  464. end
  465. def test_should_invalidate_if_no_transition_exists
  466. @object.state = 'idling'
  467. @object.state_event = 'ignite'
  468. @machines.transitions(@object, :save)
  469. assert !@object.errors.empty?
  470. end
  471. def test_should_not_invalidate_if_transition_exists
  472. @object.state_event = 'ignite'
  473. @machines.transitions(@object, :save)
  474. assert @object.errors.empty?
  475. end
  476. end