gisele-vm 0.6.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 (185) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +18 -0
  3. data/Gemfile.lock +46 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +15 -0
  6. data/README.md +10 -0
  7. data/Rakefile +11 -0
  8. data/bin/gvm +9 -0
  9. data/gisele-vm.gemspec +191 -0
  10. data/gisele-vm.noespec +31 -0
  11. data/lib/gisele-vm.rb +4 -0
  12. data/lib/gisele-vm/loader.rb +5 -0
  13. data/lib/gisele-vm/version.rb +16 -0
  14. data/lib/gisele/compiling.rb +3 -0
  15. data/lib/gisele/compiling/gisele2gts.rb +143 -0
  16. data/lib/gisele/compiling/gts.rb +74 -0
  17. data/lib/gisele/compiling/gts2bytecode.rb +127 -0
  18. data/lib/gisele/vm.rb +87 -0
  19. data/lib/gisele/vm/bytecode.rb +84 -0
  20. data/lib/gisele/vm/bytecode/builder.rb +77 -0
  21. data/lib/gisele/vm/bytecode/grammar.citrus +116 -0
  22. data/lib/gisele/vm/bytecode/grammar.rb +19 -0
  23. data/lib/gisele/vm/bytecode/grammar.sexp.yml +113 -0
  24. data/lib/gisele/vm/bytecode/printer.rb +35 -0
  25. data/lib/gisele/vm/command.rb +140 -0
  26. data/lib/gisele/vm/component.rb +91 -0
  27. data/lib/gisele/vm/console.rb +58 -0
  28. data/lib/gisele/vm/enacter.rb +29 -0
  29. data/lib/gisele/vm/errors.rb +26 -0
  30. data/lib/gisele/vm/event.rb +11 -0
  31. data/lib/gisele/vm/event_manager.rb +65 -0
  32. data/lib/gisele/vm/kernel.rb +58 -0
  33. data/lib/gisele/vm/kernel/macros.gvm +214 -0
  34. data/lib/gisele/vm/kernel/opcodes.rb +212 -0
  35. data/lib/gisele/vm/kernel/runner.rb +63 -0
  36. data/lib/gisele/vm/lifecycle.rb +72 -0
  37. data/lib/gisele/vm/logging.rb +18 -0
  38. data/lib/gisele/vm/null_object.rb +19 -0
  39. data/lib/gisele/vm/prog.rb +63 -0
  40. data/lib/gisele/vm/prog_list.rb +55 -0
  41. data/lib/gisele/vm/prog_list/memory.rb +74 -0
  42. data/lib/gisele/vm/prog_list/sqldb.rb +123 -0
  43. data/lib/gisele/vm/prog_list/storage.rb +31 -0
  44. data/lib/gisele/vm/proxy.rb +14 -0
  45. data/lib/gisele/vm/proxy/client.rb +64 -0
  46. data/lib/gisele/vm/proxy/server.rb +29 -0
  47. data/lib/gisele/vm/registry.rb +57 -0
  48. data/lib/gisele/vm/robustness.rb +31 -0
  49. data/lib/gisele/vm/simulator/resumer.rb +32 -0
  50. data/spec/command/gvm_compile.cmd +1 -0
  51. data/spec/command/gvm_compile.stdout +111 -0
  52. data/spec/command/gvm_gts.cmd +1 -0
  53. data/spec/command/gvm_gts.stdout +101 -0
  54. data/spec/command/gvm_help.cmd +1 -0
  55. data/spec/command/gvm_help.stdout +30 -0
  56. data/spec/command/gvm_version.cmd +1 -0
  57. data/spec/command/gvm_version.stdout +2 -0
  58. data/spec/command/test_command.rb +29 -0
  59. data/spec/fixtures/complete.gis +13 -0
  60. data/spec/fixtures/fake_component.rb +24 -0
  61. data/spec/fixtures/kernel.rb +39 -0
  62. data/spec/fixtures/ts.adl +11 -0
  63. data/spec/fixtures/ts.gts +20 -0
  64. data/spec/fixtures/ts.gvm +19 -0
  65. data/spec/spec_helper.rb +86 -0
  66. data/spec/test_examples.rb +29 -0
  67. data/spec/test_gisele-vm.rb +8 -0
  68. data/spec/unit/bytecode/builder/test_at.rb +56 -0
  69. data/spec/unit/bytecode/builder/test_helpers.rb +36 -0
  70. data/spec/unit/bytecode/builder/test_instruction.rb +35 -0
  71. data/spec/unit/bytecode/builder/test_to_a.rb +53 -0
  72. data/spec/unit/bytecode/bytecode.gvm +1 -0
  73. data/spec/unit/bytecode/grammar/fixtures/comments.gvm +16 -0
  74. data/spec/unit/bytecode/grammar/fixtures/every.gvm +46 -0
  75. data/spec/unit/bytecode/grammar/fixtures/singleblock.gvm +2 -0
  76. data/spec/unit/bytecode/grammar/fixtures/twoblocks.gvm +4 -0
  77. data/spec/unit/bytecode/grammar/fixtures/with_end.gvm +5 -0
  78. data/spec/unit/bytecode/grammar/test_array.rb +24 -0
  79. data/spec/unit/bytecode/grammar/test_block.rb +35 -0
  80. data/spec/unit/bytecode/grammar/test_boolean.rb +20 -0
  81. data/spec/unit/bytecode/grammar/test_constant.rb +20 -0
  82. data/spec/unit/bytecode/grammar/test_eol.rb +20 -0
  83. data/spec/unit/bytecode/grammar/test_eol_comment.rb +36 -0
  84. data/spec/unit/bytecode/grammar/test_file.rb +38 -0
  85. data/spec/unit/bytecode/grammar/test_hash.rb +33 -0
  86. data/spec/unit/bytecode/grammar/test_instruction.rb +32 -0
  87. data/spec/unit/bytecode/grammar/test_int.rb +24 -0
  88. data/spec/unit/bytecode/grammar/test_label.rb +24 -0
  89. data/spec/unit/bytecode/grammar/test_opcode.rb +23 -0
  90. data/spec/unit/bytecode/grammar/test_string.rb +25 -0
  91. data/spec/unit/bytecode/grammar/test_symbol.rb +30 -0
  92. data/spec/unit/bytecode/test_build.rb +36 -0
  93. data/spec/unit/bytecode/test_coerce.rb +41 -0
  94. data/spec/unit/bytecode/test_fetch.rb +20 -0
  95. data/spec/unit/bytecode/test_grammar.rb +30 -0
  96. data/spec/unit/bytecode/test_parse.rb +22 -0
  97. data/spec/unit/bytecode/test_plus.rb +27 -0
  98. data/spec/unit/bytecode/test_to_a.rb +19 -0
  99. data/spec/unit/bytecode/test_to_s.rb +32 -0
  100. data/spec/unit/command/code.gis +3 -0
  101. data/spec/unit/command/test_vm.rb +51 -0
  102. data/spec/unit/compiling/gisele2gts/test_on_par_st.rb +51 -0
  103. data/spec/unit/compiling/gisele2gts/test_on_seq_st.rb +46 -0
  104. data/spec/unit/compiling/gisele2gts/test_on_task_call_st.rb +37 -0
  105. data/spec/unit/compiling/gisele2gts/test_on_task_def.rb +49 -0
  106. data/spec/unit/compiling/gisele2gts/test_on_unit_def.rb +35 -0
  107. data/spec/unit/compiling/gts2bytecode/test_on_end.rb +31 -0
  108. data/spec/unit/compiling/gts2bytecode/test_on_event.rb +37 -0
  109. data/spec/unit/compiling/gts2bytecode/test_on_fork.rb +41 -0
  110. data/spec/unit/compiling/gts2bytecode/test_on_join.rb +42 -0
  111. data/spec/unit/compiling/gts2bytecode/test_on_listen.rb +36 -0
  112. data/spec/unit/compiling/gts2bytecode/test_on_nop.rb +30 -0
  113. data/spec/unit/component/test_component_name.rb +16 -0
  114. data/spec/unit/component/test_logging.rb +36 -0
  115. data/spec/unit/enacter/test_component.rb +11 -0
  116. data/spec/unit/event/test_to_s.rb +12 -0
  117. data/spec/unit/event_manager/test_component.rb +9 -0
  118. data/spec/unit/event_manager/test_subscribe.rb +40 -0
  119. data/spec/unit/event_manager/test_unsubscribe.rb +39 -0
  120. data/spec/unit/kernel/macros/test_fork.rb +37 -0
  121. data/spec/unit/kernel/macros/test_join.rb +43 -0
  122. data/spec/unit/kernel/macros/test_listen.rb +37 -0
  123. data/spec/unit/kernel/macros/test_notify.rb +57 -0
  124. data/spec/unit/kernel/macros/test_react.rb +47 -0
  125. data/spec/unit/kernel/macros/test_schedule_at.rb +30 -0
  126. data/spec/unit/kernel/opcodes/test_op_del.rb +42 -0
  127. data/spec/unit/kernel/opcodes/test_op_event.rb +25 -0
  128. data/spec/unit/kernel/opcodes/test_op_fetch.rb +27 -0
  129. data/spec/unit/kernel/opcodes/test_op_flip.rb +17 -0
  130. data/spec/unit/kernel/opcodes/test_op_fold.rb +29 -0
  131. data/spec/unit/kernel/opcodes/test_op_fork.rb +63 -0
  132. data/spec/unit/kernel/opcodes/test_op_forka.rb +51 -0
  133. data/spec/unit/kernel/opcodes/test_op_get.rb +62 -0
  134. data/spec/unit/kernel/opcodes/test_op_getr.rb +48 -0
  135. data/spec/unit/kernel/opcodes/test_op_ifenil.rb +41 -0
  136. data/spec/unit/kernel/opcodes/test_op_ifezero.rb +32 -0
  137. data/spec/unit/kernel/opcodes/test_op_invoke.rb +34 -0
  138. data/spec/unit/kernel/opcodes/test_op_nop.rb +18 -0
  139. data/spec/unit/kernel/opcodes/test_op_parent.rb +39 -0
  140. data/spec/unit/kernel/opcodes/test_op_pop.rb +22 -0
  141. data/spec/unit/kernel/opcodes/test_op_push.rb +17 -0
  142. data/spec/unit/kernel/opcodes/test_op_save.rb +32 -0
  143. data/spec/unit/kernel/opcodes/test_op_savea.rb +34 -0
  144. data/spec/unit/kernel/opcodes/test_op_self.rb +20 -0
  145. data/spec/unit/kernel/opcodes/test_op_send.rb +20 -0
  146. data/spec/unit/kernel/opcodes/test_op_set.rb +61 -0
  147. data/spec/unit/kernel/opcodes/test_op_then.rb +50 -0
  148. data/spec/unit/kernel/opcodes/test_op_unfold.rb +22 -0
  149. data/spec/unit/kernel/opcodes/test_op_uuid.rb +16 -0
  150. data/spec/unit/kernel/runner/test_pop.rb +26 -0
  151. data/spec/unit/kernel/runner/test_stack.rb +28 -0
  152. data/spec/unit/kernel/test_progress.rb +47 -0
  153. data/spec/unit/kernel/test_resume.rb +53 -0
  154. data/spec/unit/kernel/test_start.rb +36 -0
  155. data/spec/unit/prog/test_to_hash.rb +29 -0
  156. data/spec/unit/prog/test_waitlist_eq.rb +20 -0
  157. data/spec/unit/prog_list/memory/test_component.rb +9 -0
  158. data/spec/unit/prog_list/memory/test_fetch.rb +40 -0
  159. data/spec/unit/prog_list/memory/test_pick.rb +39 -0
  160. data/spec/unit/prog_list/memory/test_save.rb +91 -0
  161. data/spec/unit/prog_list/memory/test_to_relation.rb +17 -0
  162. data/spec/unit/prog_list/sqldb/test_component.rb +11 -0
  163. data/spec/unit/prog_list/sqldb/test_connect.rb +46 -0
  164. data/spec/unit/prog_list/test_memory.rb +9 -0
  165. data/spec/unit/prog_list/test_sqldb.rb +13 -0
  166. data/spec/unit/prog_list/test_storage.rb +51 -0
  167. data/spec/unit/registry/test_component.rb +9 -0
  168. data/spec/unit/registry/test_connect.rb +53 -0
  169. data/spec/unit/registry/test_disconnect.rb +51 -0
  170. data/spec/unit/registry/test_registration.rb +44 -0
  171. data/spec/unit/shared/a_component.rb +49 -0
  172. data/spec/unit/shared/a_storage.rb +114 -0
  173. data/spec/unit/test_logging.rb +46 -0
  174. data/spec/unit/test_prog.rb +57 -0
  175. data/spec/unit/test_prog_list.rb +22 -0
  176. data/spec/unit/vm/test_event_facace.rb +11 -0
  177. data/spec/unit/vm/test_initialize.rb +59 -0
  178. data/spec/unit/vm/test_proglist_facade.rb +21 -0
  179. data/tasks/debug_mail.rake +75 -0
  180. data/tasks/debug_mail.txt +13 -0
  181. data/tasks/gem.rake +73 -0
  182. data/tasks/spec_test.rake +71 -0
  183. data/tasks/unit_test.rake +76 -0
  184. data/tasks/yard.rake +51 -0
  185. metadata +493 -0
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ class Gisele::VM
3
+ describe ProgList::Memory, 'save' do
4
+ let(:list){ ProgList::Memory.new }
5
+
6
+ before do
7
+ @puids = (0..1).map{ list.save(Prog.new) }
8
+ @puids.size.should eq(2)
9
+ end
10
+
11
+ it 'helps getting a relation' do
12
+ list.to_relation.should be_a(Alf::Relation)
13
+ list.to_relation.project([:puid]).should eq(Relation(:puid => @puids))
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe ProgList::Sqldb, :sqlite => true do
5
+ subject do
6
+ ProgList::Sqldb.new sqlite_memory
7
+ end
8
+ it_should_behave_like "a component"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe ProgList::Sqldb, 'connect', :sqlite => true do
5
+
6
+ let(:db){ @db ||= ProgList::Sqldb.new(options) }
7
+
8
+ before do
9
+ db.registered(vm)
10
+ end
11
+
12
+ subject do
13
+ db.connect
14
+ end
15
+
16
+ after do
17
+ db.disconnect
18
+ db.unregistered
19
+ end
20
+
21
+ context 'when the database is unreachable' do
22
+ let(:options){ {:uri => "postgres://localhost:145/database"} }
23
+ it 'raises an error' do
24
+ lambda{
25
+ subject
26
+ }.should raise_error(Sequel::Error)
27
+ end
28
+ end
29
+
30
+ context 'when the database is creatable' do
31
+ let(:options){ sqlite_memory }
32
+ it 'returns itself' do
33
+ subject.should be_a(ProgList::Sqldb)
34
+ end
35
+ it 'sets the database under sequel_db' do
36
+ subject.sequel_db.should be_a(Sequel::Database)
37
+ end
38
+ it 'installs the schema' do
39
+ table_name = subject.send(:table_name)
40
+ subject.sequel_db.table_exists?(table_name).should be_true
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe ProgList::Memory do
5
+ subject{ @proglist ||= ProgList::Memory.new }
6
+ it_should_behave_like "a Storage"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe ProgList::Sqldb, :sqlite => true do
5
+ subject do
6
+ @proglist ||= begin
7
+ ProgList::Sqldb.new(sqlite_memory)
8
+ end
9
+ end
10
+ it_should_behave_like "a Storage"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe ProgList, 'storage' do
5
+ subject{ ProgList.storage(arg) }
6
+
7
+ before do
8
+ subject.should be_a(ProgList::Sqldb)
9
+ end
10
+
11
+ context 'without arg' do
12
+ let(:arg){ nil }
13
+ it 'uses an in-memory storage' do
14
+ subject.options[:uri].should match(/memory/)
15
+ end
16
+ end
17
+
18
+ context "with 'memory'" do
19
+ let(:arg){ "memory" }
20
+ it 'uses an in-memory storage' do
21
+ subject.options[:uri].should match(/sqlite:memory/)
22
+ end
23
+ end
24
+
25
+ context "with a specified uri" do
26
+ let(:arg){ "sqlite://ping.db" }
27
+ it 'uses an in-memory storage' do
28
+ subject.options[:uri].should eq("sqlite://ping.db")
29
+ end
30
+ end
31
+
32
+ context "when options include an uri" do
33
+ let(:arg){ {:uri => "sqlite://ping.db"} }
34
+ it 'uses an in-memory storage' do
35
+ subject.options[:uri].should eq("sqlite://ping.db")
36
+ end
37
+ end
38
+
39
+ context "with options but no uri" do
40
+ let(:arg){ {:ping => "pong"} }
41
+ it 'uses an in-memory storage' do
42
+ subject.options[:uri].should match(/sqlite:memory/)
43
+ end
44
+ it 'installs options' do
45
+ subject.options[:ping].should eq("pong")
46
+ end
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe Registry do
5
+ subject{ Registry.new(vm) }
6
+ it_should_behave_like "a component"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe Registry, "connect" do
5
+
6
+ let(:registry){ Registry.new(vm) }
7
+ let(:c1){ Component.new }
8
+ let(:c2){ Component.new }
9
+ let(:c3){ Component.new }
10
+
11
+ subject do
12
+ registry.connect
13
+ end
14
+
15
+ before do
16
+ registry.register(c1)
17
+ registry.register(c2)
18
+ registry.register(c3)
19
+ registry.components.should eq([c1, c2, c3])
20
+ end
21
+
22
+ context "when everything goes right" do
23
+ it 'connects all components' do
24
+ subject
25
+ registry.components.each do |c|
26
+ c.should be_connected
27
+ c.vm.should eq(vm)
28
+ end
29
+ end
30
+ end
31
+
32
+ context "when a component fails to load" do
33
+ before do
34
+ def c2.connect
35
+ raise ArgumentError, "blah"
36
+ end
37
+ end
38
+ it 'raise the original error' do
39
+ lambda{
40
+ subject
41
+ }.should raise_error(ArgumentError, "blah")
42
+ end
43
+ it 'disconnects connected components' do
44
+ subject rescue nil
45
+ registry.components.each do |c|
46
+ c.should_not be_connected
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe Registry, "connect" do
5
+
6
+ let(:registry){ Registry.new(vm) }
7
+ let(:c1){ Component.new }
8
+ let(:c2){ Component.new }
9
+ let(:c3){ Component.new }
10
+
11
+ subject do
12
+ registry.disconnect
13
+ end
14
+
15
+ before do
16
+ registry.register(c1)
17
+ registry.register(c2)
18
+ registry.register(c3)
19
+ registry.components.should eq([c1, c2, c3])
20
+ registry.connect
21
+ subject
22
+ end
23
+
24
+ context 'when everything goes fine' do
25
+ it 'keeps components registered' do
26
+ registry.components.should eq([c1, c2, c3])
27
+ end
28
+ it 'disconnects all components' do
29
+ registry.components.each do |c|
30
+ c.should_not be_connected
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'when a component encounters an error' do
36
+ before do
37
+ def c3.disconnect
38
+ super
39
+ raise ArgumentError
40
+ end
41
+ end
42
+ it 'silently disconnects all components' do
43
+ registry.components.each do |c|
44
+ c.should_not be_connected
45
+ end
46
+ end
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ module Gisele
3
+ class VM
4
+ describe Registry, "registration" do
5
+
6
+ subject{ Registry.new(vm) }
7
+ let(:c){ Component.new }
8
+ let(:c_prior){ Component.new }
9
+
10
+ it 'allows registering and unregistering components' do
11
+ subject.register(c)
12
+ subject.components.should be_include(c)
13
+ c.should be_registered
14
+ c.vm.should eq(vm)
15
+ subject.unregister(c)
16
+ subject.components.should_not be_include(c)
17
+ c.should_not be_registered
18
+ end
19
+
20
+ it 'allows registring prior components' do
21
+ subject.register(c)
22
+ subject.register(c_prior, true)
23
+ subject.components.should eq([c_prior, c])
24
+ c.should be_registered
25
+ end
26
+
27
+ it 'raises an error if hot registration' do
28
+ subject.connect
29
+ lambda{
30
+ subject.register(c)
31
+ }.should raise_error(NotImplementedError)
32
+ end
33
+
34
+ it 'raises an error if hot unregistration' do
35
+ subject.register(c)
36
+ subject.connect
37
+ lambda{
38
+ subject.unregister(c)
39
+ }.should raise_error(NotImplementedError)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,49 @@
1
+ module Gisele
2
+ class VM
3
+ shared_examples_for "a component" do
4
+
5
+ it 'allows vm registration and de-registration' do
6
+ the_vm = vm
7
+ subject.registered(the_vm)
8
+ subject.should be_registered
9
+ subject.vm.should eq(the_vm)
10
+ subject.unregistered
11
+ subject.should_not be_registered
12
+ subject.vm.should be_a(NullObject)
13
+ end
14
+
15
+ it 'allows vm connection and deconnection' do
16
+ the_vm = vm
17
+ subject.registered(the_vm)
18
+ subject.connect
19
+ subject.should be_connected
20
+ subject.disconnect
21
+ subject.should_not be_connected
22
+ end
23
+
24
+ it 'raises an InvalidStateError when connect used unregistered' do
25
+ unless subject.registered? # the registry is always connected
26
+ lambda{
27
+ subject.connect
28
+ }.should raise_error(InvalidStateError, "Not registered")
29
+ end
30
+ end
31
+
32
+ it 'raises an InvalidStateError when connect is badly used' do
33
+ subject.registered(vm)
34
+ subject.connect
35
+ lambda{
36
+ subject.connect
37
+ }.should raise_error(InvalidStateError, "Already connected")
38
+ end
39
+
40
+ it 'raises an InvalidStateError when disconnect is badly used' do
41
+ subject.registered(vm)
42
+ lambda{
43
+ subject.disconnect
44
+ }.should raise_error(InvalidStateError, "Not connected")
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,114 @@
1
+ module Gisele
2
+ class VM
3
+ shared_examples_for "a Storage" do
4
+
5
+ def connect_and_clear
6
+ subject.registered(vm)
7
+ subject.connect
8
+ subject.clear
9
+ end
10
+
11
+ def disconnect_and_clear
12
+ subject.clear
13
+ subject.disconnect
14
+ subject.unregistered
15
+ end
16
+
17
+ describe "connect/disconnect" do
18
+ it 'allows connecting and disconnecting' do
19
+ subject.registered(vm)
20
+ subject.connect
21
+ subject.disconnect
22
+ subject.unregistered
23
+ end
24
+ end
25
+
26
+ describe 'fetch/save' do
27
+ before(:all){ connect_and_clear }
28
+ after (:all){ disconnect_and_clear }
29
+
30
+ before do
31
+ @puid = subject.save(Prog.new)
32
+ @prog = subject.fetch(@puid)
33
+ end
34
+
35
+ it 'allows saving fresh new Prog instances' do
36
+ default = Prog.new.to_hash
37
+ default[:puid] = default[:parent] = default[:root] = @puid
38
+ default.should eq(@prog.to_hash)
39
+ end
40
+
41
+ it 'allows forking Prog instances' do
42
+ c_puid = subject.save(Prog.new :parent => @puid, :root => @puid)
43
+ child = subject.fetch(c_puid)
44
+ child.puid.should eq(c_puid)
45
+ child.parent.should eq(@puid)
46
+ child.root.should eq(@puid)
47
+ end
48
+
49
+ it 'allows saving Prog instances' do
50
+ @prog.pc = :s18
51
+ @prog.input = [:ended]
52
+ s_puid = subject.save(@prog)
53
+ fetched = subject.fetch(s_puid)
54
+ fetched.puid.should eq(@puid)
55
+ fetched.pc.should eq(:s18)
56
+ fetched.input.should eq([:ended])
57
+ end
58
+
59
+ it 'allows saving an array of Prog instances' do
60
+ @prog.pc = :s19
61
+ p1, p2 = subject.save([@prog, Prog.new])
62
+ p1.should eq(@puid)
63
+ subject.fetch(p1).pc.should eq(:s19)
64
+ subject.fetch(p2).parent.should eq(p2)
65
+ end
66
+ end
67
+
68
+ describe 'pick' do
69
+ before(:all) do
70
+ connect_and_clear
71
+ @enacted = subject.save(Prog.new :waitfor => :enacter)
72
+ @worlded = subject.save(Prog.new :waitfor => :world)
73
+ end
74
+ after (:all){ disconnect_and_clear }
75
+
76
+ it 'allows picking a prog based on a restriction' do
77
+ subject.pick(:waitfor => :enacter).should eq(subject.fetch(@enacted))
78
+ subject.pick(:waitfor => :world).should eq(subject.fetch(@worlded))
79
+ end
80
+
81
+ it 'returns nil if picking cannot be served' do
82
+ subject.pick(:waitfor => :operator).should be_nil
83
+ end
84
+ end
85
+
86
+ describe 'to_relation' do
87
+ before(:all) do
88
+ connect_and_clear
89
+ @enacted = subject.save(Prog.new :waitfor => :enacter, :pc => :s17)
90
+ @worlded = subject.save(Prog.new :waitfor => :world, :pc => :s18)
91
+ end
92
+ after (:all){ disconnect_and_clear }
93
+
94
+ it 'returns a Relation wil all Progs by default' do
95
+ rel = subject.to_relation
96
+ expected = Relation([
97
+ { :puid => @enacted, :waitlist => {}, :pc => :s17 },
98
+ { :puid => @worlded, :waitlist => {}, :pc => :s18 }
99
+ ])
100
+ rel.project([:puid, :waitlist, :pc]).should eq(expected)
101
+ end
102
+
103
+ it 'supports a restriction Hash argument' do
104
+ rel = subject.to_relation(:waitfor => :enacter)
105
+ expected = Relation([
106
+ { :puid => @enacted, :waitlist => {}, :pc => :s17 },
107
+ ])
108
+ rel.project([:puid, :waitlist, :pc]).should eq(expected)
109
+ end
110
+ end
111
+
112
+ end
113
+ end
114
+ end