flok 0.0.40 → 0.0.41

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/app/drivers/chrome/src/dispatch.js +7 -2
  3. data/app/kern/dispatch.js +10 -1
  4. data/app/kern/mod/event.js +9 -0
  5. data/app/kern/pagers/pg_mem.js +21 -0
  6. data/app/kern/pagers/pg_net_sim.js +44 -0
  7. data/app/kern/pagers/pg_spec.js +23 -0
  8. data/app/kern/services/vm.rb +60 -64
  9. data/bin/flok +44 -23
  10. data/docs/callout.md +1 -1
  11. data/docs/client_api.md +5 -2
  12. data/docs/config_yml.md +41 -0
  13. data/docs/controllers.md +4 -0
  14. data/docs/datatypes.md +5 -2
  15. data/docs/debug_server.md +2 -0
  16. data/docs/dispatch.md +8 -3
  17. data/docs/known_issues.md +6 -0
  18. data/docs/mod/event.md +25 -20
  19. data/docs/mod/persist.md +1 -1
  20. data/docs/mod/speech.md +12 -0
  21. data/docs/project.md +2 -2
  22. data/docs/services/vm.md +46 -17
  23. data/docs/services/vm/pagers.md +22 -2
  24. data/lib/flok/build.rb +0 -4
  25. data/lib/flok/user_compiler.rb +123 -47
  26. data/lib/flok/user_compiler_templates/ctable.js.erb +39 -1
  27. data/lib/flok/version.rb +1 -1
  28. data/spec/env/global.rb +1 -0
  29. data/spec/env/kern.rb +5 -1
  30. data/spec/etc/cli_spec.rb +337 -322
  31. data/spec/etc/service_compiler/config0.rb +1 -1
  32. data/spec/etc/service_compiler/config0b.rb +1 -0
  33. data/spec/etc/services_compiler_spec.rb +29 -29
  34. data/spec/etc/user_compiler/controller0b.rb +9 -0
  35. data/spec/etc/user_compiler/controller0timer.rb +16 -0
  36. data/spec/etc/user_compiler_spec.rb +24 -1
  37. data/spec/iface/driver/dispatch_spec.rb +8 -2
  38. data/spec/iface/driver/persist_spec.rb +11 -0
  39. data/spec/kern/assets/controller0defer.rb +18 -0
  40. data/spec/kern/assets/controller0defer0.rb +13 -0
  41. data/spec/kern/assets/controller0defer2.rb +17 -0
  42. data/spec/kern/assets/global_on_entry.rb +8 -0
  43. data/spec/kern/assets/global_on_entry2.rb +16 -0
  44. data/spec/kern/assets/global_on_entry3.rb +17 -0
  45. data/spec/kern/assets/global_on_entry4.rb +12 -0
  46. data/spec/kern/assets/interval.rb +29 -0
  47. data/spec/kern/assets/interval2.rb +33 -0
  48. data/spec/kern/assets/interval3.rb +39 -0
  49. data/spec/kern/assets/service1.rb +4 -1
  50. data/spec/kern/assets/service_controller1.rb +11 -0
  51. data/spec/kern/assets/specimin/controller0.rb +74 -0
  52. data/spec/kern/assets/vm/config5.rb +20 -0
  53. data/spec/kern/assets/vm/config6.rb +20 -0
  54. data/spec/kern/assets/vm/controller10.rb +1 -1
  55. data/spec/kern/assets/vm/controller11.rb +1 -1
  56. data/spec/kern/assets/vm/controller12.rb +1 -1
  57. data/spec/kern/assets/vm/controller13.rb +1 -1
  58. data/spec/kern/assets/vm/controller16b.rb +28 -0
  59. data/spec/kern/assets/vm/controller18.rb +1 -1
  60. data/spec/kern/assets/vm/controller21.rb +1 -1
  61. data/spec/kern/assets/vm/controller22.rb +8 -0
  62. data/spec/kern/assets/vm/controller_exc_ewatch.rb +1 -0
  63. data/spec/kern/assets/vm/controller_exc_ewatch2.rb +30 -0
  64. data/spec/kern/assets/vm/controller_exc_ewatch3.rb +16 -0
  65. data/spec/kern/assets/vm/controller_exc_ewatch4.rb +16 -0
  66. data/spec/kern/assets/vm/macros/copy_page_c.rb +1 -0
  67. data/spec/kern/assets/vm/macros/copy_page_ch.rb +25 -0
  68. data/spec/kern/assets/vm/macros/entry_del_c.rb +1 -0
  69. data/spec/kern/assets/vm/macros/entry_del_ch.rb +20 -0
  70. data/spec/kern/assets/vm/macros/entry_insert_c.rb +1 -0
  71. data/spec/kern/assets/vm/macros/entry_insert_ch.rb +23 -0
  72. data/spec/kern/assets/vm/macros/entry_mutable_c.rb +8 -7
  73. data/spec/kern/assets/vm/macros/entry_mutable_ch.rb +34 -0
  74. data/spec/kern/assets/vm/macros/new_page_c.rb +1 -1
  75. data/spec/kern/assets/vm/macros/new_page_c2.rb +1 -1
  76. data/spec/kern/assets/vm/macros/new_page_ch.rb +7 -0
  77. data/spec/kern/assets/vm/pg_mem/config.rb +10 -0
  78. data/spec/kern/assets/vm/pg_mem/config1.rb +10 -0
  79. data/spec/kern/assets/vm/pg_mem/config2.rb +10 -0
  80. data/spec/kern/assets/vm/pg_mem/config3.rb +15 -0
  81. data/spec/kern/assets/vm/pg_mem/write.rb +23 -0
  82. data/spec/kern/assets/vm/pg_mem/write2.rb +38 -0
  83. data/spec/kern/assets/vm/pg_net_sim/config.rb +10 -0
  84. data/spec/kern/assets/vm/pg_net_sim/nothing.rb +12 -0
  85. data/spec/kern/assets/vm/pg_net_sim/pages.json +1 -0
  86. data/spec/kern/assets/vm/pg_net_sim/watch.rb +18 -0
  87. data/spec/kern/callout_spec.rb +1 -1
  88. data/spec/kern/controller_macro_spec.rb +153 -20
  89. data/spec/kern/controller_spec.rb +232 -1
  90. data/spec/kern/debug_ui_spec.rb +235 -235
  91. data/spec/kern/event_spec.rb +112 -0
  92. data/spec/kern/service_controller_spec.rb +14 -2
  93. data/spec/kern/vm_service_mem_pagers_spec.rb +117 -0
  94. data/spec/kern/vm_service_net_sim_pager_spec.rb +97 -0
  95. data/spec/kern/vm_service_spec.rb +304 -17
  96. data/spec/kern/vm_service_spec2.rb +39 -0
  97. metadata +88 -6
  98. data/app/kern/pagers/mem_pager.js +0 -2
  99. data/app/kern/pagers/pg_spec0.js +0 -20
  100. data/lib/flok/project_template/Guardfile +0 -7
  101. data/lib/flok/project_template/config/config.yml +0 -1
@@ -0,0 +1,112 @@
1
+ Dir.chdir File.join File.dirname(__FILE__), '../../'
2
+ require './spec/env/kern.rb'
3
+ require './spec/lib/helpers.rb'
4
+ require './spec/lib/io_extensions.rb'
5
+ require './spec/lib/rspec_extensions.rb'
6
+
7
+ RSpec.describe "kern:event_spec" do
8
+ include_context "kern"
9
+
10
+ it "Can call int_event_defer" do
11
+ #Compile the controller
12
+ ctx = flok_new_user File.read('./spec/kern/assets/controller0.rb')
13
+
14
+ #Register callout
15
+ ctx.eval %{
16
+ base = _embed("my_controller", 0, {}, null);
17
+
18
+ //Queue up a deferred event
19
+ int_event_defer(base, "defer_res", {});
20
+ }
21
+
22
+ edefer_q = ctx.dump("edefer_q")
23
+ base = ctx.eval("base")
24
+ expect(edefer_q).to eq([
25
+ base, "defer_res", {}
26
+ ])
27
+ end
28
+
29
+ it "Does call if_dispatch with an 'i' for incomplete" do
30
+ #Compile the controller
31
+ ctx = flok_new_user File.read('./spec/kern/assets/controller0.rb')
32
+
33
+ #Register callout
34
+ ctx.eval %{
35
+ base = _embed("my_controller", 0, {}, null);
36
+
37
+ //Queue up two deferred event b/c the first will get eaten
38
+ int_event_defer(base, "defer_res", {});
39
+ int_event_defer(base, "defer_res", {});
40
+
41
+ //Drain queue
42
+ int_dispatch([]);
43
+ }
44
+
45
+ #Incomplete should have been added
46
+ q = @driver.dump_q
47
+ expect(q[0]).to eq("i")
48
+ end
49
+
50
+ it "Does call the event trigger for the controller after the dispatch" do
51
+ #Compile the controller
52
+ ctx = flok_new_user File.read('./spec/kern/assets/controller0defer.rb')
53
+
54
+ #Register callout
55
+ ctx.eval %{
56
+ base = _embed("my_controller", 0, {}, null);
57
+ }
58
+
59
+ #At this point, the synchronous event should have been dispatched in the _embed
60
+ #because int_event is located in the controller on_entry
61
+ sync_res_params = ctx.dump("sync_res_params")
62
+ expect(sync_res_params).to eq({
63
+ "foo_sync" => "bar"
64
+ })
65
+
66
+ #But the deferred response should only be available during the
67
+ #next int_disp
68
+ expect {
69
+ ctx.dump("defer_res_params")
70
+ }.to raise_exception
71
+
72
+ ctx.eval("int_dispatch([])")
73
+
74
+ #At this point, we only have one int_dispatch, so the event
75
+ #should never have been de-queued because it will on teh second one
76
+ defer_res_params = ctx.dump("defer_res_params")
77
+ expect(defer_res_params).to eq({
78
+ "foo" => "bar"
79
+ })
80
+ end
81
+
82
+ it "Does call the event trigger for the controller after the dispatch only one at a time" do
83
+ #Compile the controller
84
+ ctx = flok_new_user File.read('./spec/kern/assets/controller0defer2.rb')
85
+
86
+ #Register callout
87
+ ctx.eval %{
88
+ base = _embed("my_controller", 0, {}, null);
89
+ int_dispatch([]);
90
+ }
91
+
92
+ #Should have dequeued the first asynchronous event callback
93
+ defer_res_params = ctx.dump("defer_res_params")
94
+ expect(defer_res_params).to eq({
95
+ "foo" => "bar"
96
+ })
97
+
98
+ #But the second one should not have dequeued yet
99
+ expect {
100
+ ctx.dump("defer_res2_params")
101
+ }.to raise_exception
102
+
103
+ #Until we throw another int_dispatch
104
+ ctx.eval("int_dispatch([])")
105
+
106
+ #And now it should be there
107
+ defer_res2_params = ctx.dump("defer_res2_params")
108
+ expect(defer_res2_params).to eq({
109
+ "foo" => "bar"
110
+ })
111
+ end
112
+ end
@@ -140,7 +140,7 @@ RSpec.describe "kern:service_controller_spec" do
140
140
  int_dispatch([3, "int_event", base, "next", {}]);
141
141
  }
142
142
 
143
- 100.times do
143
+ 103.times do
144
144
  @driver.int "int_timer"
145
145
  end
146
146
 
@@ -150,11 +150,23 @@ RSpec.describe "kern:service_controller_spec" do
150
150
  int_dispatch([3, "int_event", base, "next", {}]);
151
151
  }
152
152
 
153
+ #Should fire 25 times, but not the 26th
154
+ 103.times do
155
+ @driver.int "int_timer"
156
+ end
157
+
158
+ #Switch back into the action
159
+ ctx.eval %{
160
+ //Drain queue
161
+ int_dispatch([3, "int_event", base, "next", {}]);
162
+ int_dispatch([3, "int_event", base, "next", {}]);
163
+ }
164
+
153
165
  100.times do
154
166
  @driver.int "int_timer"
155
167
  end
156
168
 
157
- expect(ctx.eval("every_ticks")).to eq(25)
169
+ expect(ctx.eval("every_ticks")).to eq(50)
158
170
  end
159
171
 
160
172
  it "Does have all the right variables after sending a custom event to the service and a timer event has fired" do
@@ -0,0 +1,117 @@
1
+ #The pg_mem0 pager
2
+
3
+ Dir.chdir File.join File.dirname(__FILE__), '../../'
4
+ require './spec/env/kern.rb'
5
+ require './spec/lib/helpers.rb'
6
+ require './spec/lib/io_extensions.rb'
7
+ require './spec/lib/rspec_extensions.rb'
8
+ require 'zlib'
9
+
10
+ RSpec.describe "kern:vm_service_mem_pagers" do
11
+ include Zlib
12
+ include_context "kern"
13
+
14
+ it "Can initialize the pg_mem0 pager" do
15
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/pg_mem/config.rb")
16
+ ctx.eval %{
17
+ //Call embed on main root view
18
+ base = _embed("my_controller", 0, {}, null);
19
+
20
+ //Drain queue
21
+ int_dispatch([]);
22
+ }
23
+
24
+ res = ctx.eval("pg_mem0_spec_did_init")
25
+ expect(res).to eq(true)
26
+ end
27
+
28
+ it "Can make a write request to pg_mem0 and have that written in cache" do
29
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_mem/write.rb'), File.read("./spec/kern/assets/vm/pg_mem/config.rb")
30
+ ctx.eval %{
31
+ //Call embed on main root view
32
+ base = _embed("my_controller", 0, {}, null);
33
+
34
+ //Drain queue
35
+ int_dispatch([]);
36
+ }
37
+
38
+ page = ctx.dump "page"
39
+ vm_cache = ctx.dump("vm_cache")
40
+ expect(page).to eq(vm_cache["local"]["test"])
41
+ end
42
+
43
+ it "Can initialize the pg_mem1 pager" do
44
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/pg_mem/config1.rb")
45
+ ctx.eval %{
46
+ //Call embed on main root view
47
+ base = _embed("my_controller", 0, {}, null);
48
+
49
+ //Drain queue
50
+ int_dispatch([]);
51
+ }
52
+
53
+ res = ctx.eval("pg_mem1_spec_did_init")
54
+ expect(res).to eq(true)
55
+ end
56
+
57
+ it "Can make a write request to pg_mem1 and have that written in cache" do
58
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_mem/write.rb'), File.read("./spec/kern/assets/vm/pg_mem/config1.rb")
59
+ ctx.eval %{
60
+ //Call embed on main root view
61
+ base = _embed("my_controller", 0, {}, null);
62
+
63
+ //Drain queue
64
+ int_dispatch([]);
65
+ }
66
+
67
+ page = ctx.dump "page"
68
+ vm_cache = ctx.dump("vm_cache")
69
+ expect(page).to eq(vm_cache["local"]["test"])
70
+ end
71
+
72
+ it "Can initialize the pg_mem2 pager" do
73
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/pg_mem/config2.rb")
74
+ ctx.eval %{
75
+ //Call embed on main root view
76
+ base = _embed("my_controller", 0, {}, null);
77
+
78
+ //Drain queue
79
+ int_dispatch([]);
80
+ }
81
+
82
+ res = ctx.eval("pg_mem2_spec_did_init")
83
+ expect(res).to eq(true)
84
+ end
85
+
86
+ it "Can make a write request to pg_mem2 and have that written in cache" do
87
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_mem/write.rb'), File.read("./spec/kern/assets/vm/pg_mem/config2.rb")
88
+ ctx.eval %{
89
+ //Call embed on main root view
90
+ base = _embed("my_controller", 0, {}, null);
91
+
92
+ //Drain queue
93
+ int_dispatch([]);
94
+ }
95
+
96
+ page = ctx.dump "page"
97
+ vm_cache = ctx.dump("vm_cache")
98
+ expect(page).to eq(vm_cache["local"]["test"])
99
+ end
100
+
101
+ it "Can use pg_mem0 and pg_mem1 at the same time" do
102
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_mem/write2.rb'), File.read("./spec/kern/assets/vm/pg_mem/config3.rb")
103
+ ctx.eval %{
104
+ //Call embed on main root view
105
+ base = _embed("my_controller", 0, {}, null);
106
+
107
+ //Drain queue
108
+ int_dispatch([]);
109
+ }
110
+
111
+ page = ctx.dump "page"
112
+ page2 = ctx.dump "page2"
113
+ vm_cache = ctx.dump("vm_cache")
114
+ expect(page).to eq(vm_cache["local0"]["test"])
115
+ expect(page2).to eq(vm_cache["local1"]["test"])
116
+ end
117
+ end
@@ -0,0 +1,97 @@
1
+ #The pg_mem0 pager
2
+
3
+ Dir.chdir File.join File.dirname(__FILE__), '../../'
4
+ require './spec/env/kern.rb'
5
+ require './spec/lib/helpers.rb'
6
+ require './spec/lib/io_extensions.rb'
7
+ require './spec/lib/rspec_extensions.rb'
8
+ require 'zlib'
9
+
10
+ RSpec.describe "kern:vm_service_net_sim_pager" do
11
+ include Zlib
12
+ include_context "kern"
13
+
14
+ it "Can initialize the pg_net_sim pager" do
15
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_net_sim/nothing.rb'), File.read("./spec/kern/assets/vm/pg_net_sim/config.rb")
16
+ ctx.eval %{
17
+ //Call embed on main root view
18
+ base = _embed("my_controller", 0, {}, null);
19
+
20
+ //Drain queue
21
+ int_dispatch([]);
22
+ }
23
+
24
+ res = ctx.eval("pg_net_sim_spec_did_init")
25
+ expect(res).to eq(true)
26
+ end
27
+
28
+ it "Can load the pg_net_sim pager with data" do
29
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_net_sim/nothing.rb'), File.read("./spec/kern/assets/vm/pg_net_sim/config.rb")
30
+ ctx.eval %{
31
+ //Call embed on main root view
32
+ base = _embed("my_controller", 0, {}, null);
33
+
34
+ //Drain queue
35
+ int_dispatch([]);
36
+
37
+ var json = #{File.read("./spec/kern/assets/vm/pg_net_sim/pages.json")};
38
+ pg_net_sim_load_pages(json)
39
+ }
40
+
41
+ pg_net_sim_stored_pages = ctx.dump("pg_net_sim_stored_pages")
42
+ res = ctx.eval("pg_net_sim_spec_did_init")
43
+ expect(res).to eq(true)
44
+
45
+ #Simulate cache build for pages, the pg_net_sim stores like vm_cache from array
46
+ pages = JSON.parse(File.read("./spec/kern/assets/vm/pg_net_sim/pages.json"))
47
+ pages_cache = {}
48
+ pages.each do |p|
49
+ pages_cache[p["_id"]] = p
50
+ end
51
+ expect(pg_net_sim_stored_pages).to eq(pages_cache)
52
+ end
53
+
54
+ it "Can watch pg_net_sim and not get a response back before 2 seconds (by design)" do
55
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_net_sim/watch.rb'), File.read("./spec/kern/assets/vm/pg_net_sim/config.rb")
56
+ ctx.eval %{
57
+ var json = #{File.read("./spec/kern/assets/vm/pg_net_sim/pages.json")};
58
+ pg_net_sim_load_pages(json)
59
+
60
+ //Call embed on main root view
61
+ base = _embed("my_controller", 0, {}, null);
62
+
63
+ //Drain queue
64
+ int_dispatch([]);
65
+ }
66
+
67
+ expect {
68
+ pages = JSON.parse(File.read("./spec/kern/assets/vm/pg_net_sim/pages.json"))
69
+ read_res_params = ctx.dump("read_res_params")
70
+ expect(read_res_params).to eq(pages[0])
71
+ }.to raise_error
72
+ end
73
+
74
+ it "Can watch pg_net_sim and get a response back after 2 seconds" do
75
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/pg_net_sim/watch.rb'), File.read("./spec/kern/assets/vm/pg_net_sim/config.rb")
76
+ ctx.eval %{
77
+ var json = #{File.read("./spec/kern/assets/vm/pg_net_sim/pages.json")};
78
+ pg_net_sim_load_pages(json)
79
+
80
+ //Call embed on main root view
81
+ base = _embed("my_controller", 0, {}, null);
82
+
83
+ //Drain queue
84
+ int_dispatch([]);
85
+ }
86
+
87
+ (4*2).times do
88
+ @driver.int "int_timer"
89
+ end
90
+
91
+ ctx.eval "int_dispatch([]);"
92
+
93
+ pages = JSON.parse(File.read("./spec/kern/assets/vm/pg_net_sim/pages.json"))
94
+ read_res_params = ctx.dump("read_res_params")
95
+ expect(read_res_params).to eq(pages[0])
96
+ end
97
+ end
@@ -11,7 +11,30 @@ RSpec.describe "kern:vm_service" do
11
11
  include Zlib
12
12
  include_context "kern"
13
13
 
14
- it "vm_rehash_page can calculate the hash correctly" do
14
+ it "Contains a preloaded vm_cache, vm_dirty, and vm_notify_map for each namespace with a blank hash" do
15
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config5.rb")
16
+ ctx.eval %{
17
+ base = _embed("my_controller", 0, {}, null);
18
+
19
+ //Drain queue
20
+ int_dispatch([]);
21
+ }
22
+
23
+ vm_cache = ctx.dump("vm_cache")
24
+ vm_dirty = ctx.dump("vm_dirty")
25
+ vm_notify_map = ctx.dump("vm_notify_map")
26
+
27
+ res = {
28
+ "spec0" => {},
29
+ "spec1" => {}
30
+ }
31
+
32
+ expect(vm_cache).to eq(res)
33
+ expect(vm_dirty ).to eq(res)
34
+ expect(vm_notify_map).to eq(res)
35
+ end
36
+
37
+ it "vm_rehash_page can calculate the hash correctly for arrays" do
15
38
  ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config3.rb")
16
39
 
17
40
  #Run the check
@@ -19,6 +42,7 @@ it "vm_rehash_page can calculate the hash correctly" do
19
42
  //Manually construct a page
20
43
  var page = {
21
44
  _head: null,
45
+ _type: "array",
22
46
  _next: null,
23
47
  _id: "hello",
24
48
  entries: [
@@ -38,6 +62,7 @@ it "vm_rehash_page can calculate the hash correctly" do
38
62
  #Expect the same hash
39
63
  expect(page).to eq({
40
64
  "_head" => nil,
65
+ "_type" => "array",
41
66
  "_next" => nil,
42
67
  "_id" => "hello",
43
68
  "entries" => [
@@ -47,13 +72,63 @@ it "vm_rehash_page can calculate the hash correctly" do
47
72
  })
48
73
  end
49
74
 
50
- it "vm_rehash_page can calculate the hash correctly with head and next" do
75
+ it "vm_rehash_page can calculate the hash correctly for hashes" do
51
76
  ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config3.rb")
52
77
 
53
78
  #Run the check
54
79
  res = ctx.eval %{
55
80
  //Manually construct a page
56
81
  var page = {
82
+ _head: null,
83
+ "_type": "hash",
84
+ _next: null,
85
+ _id: "hello",
86
+ entries: {
87
+ "my_key": {_sig: "a"},
88
+ "my_key2": {_sig: "b"},
89
+ "my_key3": {_sig: "c"},
90
+ }
91
+ }
92
+
93
+ vm_rehash_page(page);
94
+ }
95
+
96
+ #Calculate hash ourselves
97
+ hash = crc32("hello")
98
+
99
+ #XOR the _sigs for the hash calculations
100
+ a = crc32("a", 0)
101
+ b = crc32("b", 0)
102
+ c = crc32("c", 0)
103
+ hash = crc32((a + b + c).to_s, hash)
104
+
105
+ page = JSON.parse(ctx.eval("JSON.stringify(page)"))
106
+ page = JSON.parse(ctx.eval("JSON.stringify(page)"))
107
+
108
+ #Expect the same hash
109
+ expect(page).to eq({
110
+ "_head" => nil,
111
+ "_next" => nil,
112
+ "_type" => "hash",
113
+ "_id" => "hello",
114
+ "entries" => {
115
+ "my_key" => {"_sig" => "a"},
116
+ "my_key2" => {"_sig" => "b"},
117
+ "my_key3" => {"_sig" => "c"},
118
+ },
119
+ "_hash" => hash.to_s
120
+ })
121
+ end
122
+
123
+
124
+ it "vm_rehash_page can calculate the hash correctly with head and next for an array" do
125
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config3.rb")
126
+
127
+ #Run the check
128
+ res = ctx.eval %{
129
+ //Manually construct a page
130
+ var page = {
131
+ _type: "array",
57
132
  _head: "a",
58
133
  _next: "b",
59
134
  _id: "hello",
@@ -75,6 +150,7 @@ it "vm_rehash_page can calculate the hash correctly" do
75
150
  #Expect the same hash
76
151
  expect(page).to eq({
77
152
  "_head" => "a",
153
+ "_type" => "array",
78
154
  "_next" => "b",
79
155
  "_id" => "hello",
80
156
  "entries" => [
@@ -93,6 +169,7 @@ it "vm_rehash_page can calculate the hash correctly" do
93
169
  page = {
94
170
  _head: "a",
95
171
  _next: "b",
172
+ _type: "array",
96
173
  _id: "hello",
97
174
  entries: [
98
175
  {_id: "hello2", _sig: "nohteunth"},
@@ -167,6 +244,7 @@ it "vm_rehash_page can calculate the hash correctly" do
167
244
  _head: "a",
168
245
  _next: "b",
169
246
  _id: "my_key",
247
+ _type: "array",
170
248
  entries: [
171
249
  {_id: "hello2", _sig: "nohteunth"},
172
250
  ]
@@ -198,8 +276,8 @@ it "vm_rehash_page can calculate the hash correctly" do
198
276
  }])
199
277
  end
200
278
 
201
- it "throws an exception if multiple watches are attempted" do
202
- ctx = flok_new_user File.read('./spec/kern/assets/vm/controller_exc_2watch.rb'), File.read("./spec/kern/assets/vm/config4.rb")
279
+ it "does not throw an exception if multiple watches are attempted" do
280
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller_exc_2watch.rb'), File.read("./spec/kern/assets/vm/config6.rb")
203
281
 
204
282
  expect {
205
283
  ctx.eval %{
@@ -208,11 +286,31 @@ it "vm_rehash_page can calculate the hash correctly" do
208
286
  //Drain queue
209
287
  int_dispatch([]);
210
288
  }
211
- }.to raise_exception
289
+ }.not_to raise_exception
290
+
291
+ bp = ctx.eval("base")
292
+ vm_notify_map = ctx.dump("vm_notify_map")
293
+ vm_bp_to_nmap = ctx.dump("vm_bp_to_nmap")
294
+
295
+ expect(vm_notify_map).to eq({
296
+ "spec" => {
297
+ "test" => [bp]
298
+ },
299
+ "spec1" => {}
300
+ })
301
+
302
+ expect(vm_bp_to_nmap).to eq({
303
+ bp.to_s => {
304
+ "spec" => {
305
+ "test" => [[bp], 0]
306
+ }
307
+ }
308
+ })
309
+
212
310
  end
213
311
 
214
- it "throws an exception if unwatch is called before watch" do
215
- ctx = flok_new_user File.read('./spec/kern/assets/vm/controller_exc_ewatch.rb'), File.read("./spec/kern/assets/vm/config4.rb")
312
+ it "does not throw an exception if multiple unwatches are requested" do
313
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller_exc_ewatch.rb'), File.read("./spec/kern/assets/vm/config6.rb")
216
314
 
217
315
  expect {
218
316
  ctx.eval %{
@@ -221,7 +319,95 @@ it "vm_rehash_page can calculate the hash correctly" do
221
319
  //Drain queue
222
320
  int_dispatch([]);
223
321
  }
224
- }.to raise_exception
322
+ }.not_to raise_exception
323
+
324
+ bp = ctx.eval("base")
325
+ vm_notify_map = ctx.dump("vm_notify_map")
326
+ vm_bp_to_nmap = ctx.dump("vm_bp_to_nmap")
327
+
328
+ expect(vm_notify_map).to eq({
329
+ "spec" => {
330
+ },
331
+ "spec1" => {}
332
+ })
333
+
334
+ expect(vm_bp_to_nmap).to eq({
335
+ bp.to_s => {}
336
+ })
337
+
338
+ end
339
+
340
+ it "does not throw an exception if unwatch is called before watch on a particular controller; but it was already watched at one point" do
341
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller_exc_ewatch2.rb'), File.read("./spec/kern/assets/vm/config6.rb")
342
+
343
+ expect {
344
+ ctx.eval %{
345
+ base = _embed("my_watch_controller", 1, {}, null);
346
+ base = _embed("my_controller", 1, {}, null);
347
+
348
+ //Drain queue
349
+ int_dispatch([]);
350
+ }
351
+ }.not_to raise_exception
352
+ end
353
+
354
+ it "does allow watch, unwatch, and then re-watch to work" do
355
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller_exc_ewatch3.rb'), File.read("./spec/kern/assets/vm/config6.rb")
356
+
357
+ ctx.eval %{
358
+ base = _embed("my_controller", 1, {}, null);
359
+
360
+ //Drain queue
361
+ int_dispatch([]);
362
+ }
363
+
364
+ bp = ctx.eval("base")
365
+ vm_notify_map = ctx.dump("vm_notify_map")
366
+ vm_bp_to_nmap = ctx.dump("vm_bp_to_nmap")
367
+
368
+ expect(vm_notify_map).to eq({
369
+ "spec" => {
370
+ "test" => [bp]
371
+ },
372
+ "spec1" => {}
373
+ })
374
+
375
+ expect(vm_bp_to_nmap).to eq({
376
+ bp.to_s => {
377
+ "spec" => {
378
+ "test" => [[bp], 0]
379
+ }
380
+ }
381
+ })
382
+ end
383
+
384
+ it "does allow unwatch, watch, and then re-unwatch to work" do
385
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller_exc_ewatch4.rb'), File.read("./spec/kern/assets/vm/config6.rb")
386
+
387
+ ctx.eval %{
388
+ base = _embed("my_controller", 1, {}, null);
389
+
390
+ //Drain queue
391
+ int_dispatch([]);
392
+ }
393
+
394
+ bp = ctx.eval("base")
395
+ vm_notify_map = ctx.dump("vm_notify_map")
396
+ vm_bp_to_nmap = ctx.dump("vm_bp_to_nmap")
397
+
398
+ expect(vm_notify_map).to eq({
399
+ "spec" => {
400
+ "test" => []
401
+ },
402
+ "spec1" => {}
403
+ })
404
+
405
+ expect(vm_bp_to_nmap).to eq({
406
+ bp.to_s => {
407
+ "spec" => {
408
+ }
409
+ }
410
+ })
225
411
  end
226
412
 
227
413
  it "multiple sequential watch requests from two controllers for a namespace do not hit the pager multiple times" do
@@ -312,17 +498,30 @@ it "vm_rehash_page can calculate the hash correctly" do
312
498
  expect(read_res_params).to eq(vm_write_list)
313
499
  end
314
500
 
315
- it "does send two watch callbacks to a controller if there is cached content" do
501
+ it "non-sync watch does send two watch callbacks to a controller if there is cached content" do
316
502
  ctx = flok_new_user File.read('./spec/kern/assets/vm/controller12.rb'), File.read("./spec/kern/assets/vm/config4.rb")
317
503
 
318
504
  ctx.eval %{
319
505
  base = _embed("my_controller", 1, {}, null);
320
-
321
- //Drain queue
322
- int_dispatch([]);
323
506
  }
324
507
 
508
+ #Should not have read anything at this point in time
509
+ read_res_params = JSON.parse(ctx.eval("JSON.stringify(read_res_params)"))
510
+ expect(read_res_params.length).to eq(0)
511
+
512
+ ctx.eval("int_dispatch([])")
513
+
514
+ #Now we read the first after it de-queued
325
515
  read_res_params = JSON.parse(ctx.eval("JSON.stringify(read_res_params)"))
516
+ expect(read_res_params.length).to eq(1)
517
+
518
+ ctx.eval("int_dispatch([])")
519
+
520
+ #And now the second
521
+ read_res_params = JSON.parse(ctx.eval("JSON.stringify(read_res_params)"))
522
+ expect(read_res_params.length).to eq(2)
523
+
524
+ #And they should have been read in order
326
525
  vm_write_list = JSON.parse(ctx.eval("JSON.stringify(vm_write_list)"));
327
526
  expect(read_res_params).to eq(vm_write_list)
328
527
  end
@@ -439,6 +638,30 @@ it "vm_rehash_page can calculate the hash correctly" do
439
638
  })
440
639
  end
441
640
 
641
+ it "Does not crash when a new a controller disconnects without watches" do
642
+ ctx = flok_new_user File.read('./spec/kern/assets/vm/controller16b.rb'), File.read("./spec/kern/assets/vm/config4.rb")
643
+
644
+ ctx.eval %{
645
+ base = _embed("my_controller", 1, {}, null);
646
+
647
+ //Drain queue
648
+ int_dispatch([3, "int_event", base, "next", {}]);
649
+ }
650
+
651
+ #vm_bp_To_nmap should be blank
652
+ base = ctx.eval("base")
653
+ vm_bp_to_nmap = JSON.parse(ctx.eval("JSON.stringify(vm_bp_to_nmap)"));
654
+ expect(vm_bp_to_nmap).to eq({})
655
+
656
+ #vm_notify_map should not contain the entries for the base address anymore
657
+ base = ctx.eval("base")
658
+ vm_notify_map = JSON.parse(ctx.eval("JSON.stringify(vm_notify_map)"));
659
+ expect(vm_notify_map).to eq({
660
+ "spec" => {
661
+ }
662
+ })
663
+ end
664
+
442
665
  it "Erases entries in vm_bp_to_nmap and vm_notify_map for a controller that disconnects" do
443
666
  ctx = flok_new_user File.read('./spec/kern/assets/vm/controller16.rb'), File.read("./spec/kern/assets/vm/config4.rb")
444
667
 
@@ -499,6 +722,7 @@ it "vm_rehash_page can calculate the hash correctly" do
499
722
  _head: "a",
500
723
  _next: "b",
501
724
  _id: "hello",
725
+ _type: "array",
502
726
  entries: [
503
727
  {_id: "hello2", _sig: "nohteunth"},
504
728
  ]
@@ -703,7 +927,63 @@ it "vm_rehash_page can calculate the hash correctly" do
703
927
  })
704
928
  end
705
929
 
706
- it "Responds twice to watch with a missing cache but where the disk has a copy and then the pager responds" do
930
+ #it "Responds twice to watch with a missing cache but where the disk has a copy and then the pager responds" do
931
+ #ctx = flok_new_user File.read('./spec/kern/assets/vm/controller20.rb'), File.read("./spec/kern/assets/vm/config4.rb")
932
+
933
+ #ctx.eval %{
934
+ #base = _embed("my_controller", 1, {}, null);
935
+
936
+ #//Manually construct a page
937
+ #page = {
938
+ #_head: null,
939
+ #_next: null,
940
+ #_id: "hello",
941
+ #entries: [
942
+ #{_id: "hello2", _sig: "nohteunth"},
943
+ #]
944
+ #}
945
+
946
+ #//Manually construct another page that would normally be written
947
+ #//by a 'pager' to the cache
948
+ #page2 = {
949
+ #_head: null,
950
+ #_next: null,
951
+ #_id: "hello",
952
+ #entries: [
953
+ #{_id: "hello2", _sig: "nohteunth"},
954
+ #{_id: "hello3", _sig: "athoeuntz"}
955
+ #]
956
+ #}
957
+
958
+ #//Recalculate hashes
959
+ #vm_rehash_page(page);
960
+ #vm_rehash_page(page2);
961
+
962
+ #//Drain queue
963
+ #int_dispatch([]);
964
+ #}
965
+
966
+ ##Copies of JS pages in ruby dictionary format
967
+ #page = JSON.parse(ctx.eval("JSON.stringify(page)"))
968
+ #page2 = JSON.parse(ctx.eval("JSON.stringify(page2)"))
969
+
970
+ ##At this point, flok should have attempted to grab a page to fill
971
+ ##the *now* blank cache. We are going to send it the first page.
972
+ #@driver.ignore_up_to "if_per_get", 2
973
+ #@driver.get "if_per_get", 2
974
+ #@driver.int "int_per_get_res", ["vm", "spec", page]
975
+
976
+ ##Now, we pretend that a pager has written to the cache because it has
977
+ ##received data back
978
+ #ctx.eval(%{vm_cache_write("spec", page2)})
979
+
980
+ #res = JSON.parse(ctx.eval("JSON.stringify(read_res)"))
981
+ #expect(res).to eq([
982
+ #page, page2
983
+ #])
984
+ #end
985
+
986
+ it "Responds once to watch with a missing cache but where the pager responds before the disk for array" do
707
987
  ctx = flok_new_user File.read('./spec/kern/assets/vm/controller20.rb'), File.read("./spec/kern/assets/vm/config4.rb")
708
988
 
709
989
  ctx.eval %{
@@ -714,6 +994,7 @@ it "vm_rehash_page can calculate the hash correctly" do
714
994
  _head: null,
715
995
  _next: null,
716
996
  _id: "hello",
997
+ _type: "array",
717
998
  entries: [
718
999
  {_id: "hello2", _sig: "nohteunth"},
719
1000
  ]
@@ -725,6 +1006,7 @@ it "vm_rehash_page can calculate the hash correctly" do
725
1006
  _head: null,
726
1007
  _next: null,
727
1008
  _id: "hello",
1009
+ _type: "array",
728
1010
  entries: [
729
1011
  {_id: "hello2", _sig: "nohteunth"},
730
1012
  {_id: "hello3", _sig: "athoeuntz"}
@@ -747,19 +1029,22 @@ it "vm_rehash_page can calculate the hash correctly" do
747
1029
  #the *now* blank cache. We are going to send it the first page.
748
1030
  @driver.ignore_up_to "if_per_get", 2
749
1031
  @driver.get "if_per_get", 2
750
- @driver.int "int_per_get_res", ["vm", "spec", page]
751
1032
 
752
1033
  #Now, we pretend that a pager has written to the cache because it has
753
1034
  #received data back
754
1035
  ctx.eval(%{vm_cache_write("spec", page2)})
755
1036
 
1037
+ #And then we let the cache from disk reply, which should be ignored
1038
+ #because the cache is already there from the pager
1039
+ @driver.int "int_per_get_res", ["vm", "spec", page]
1040
+
756
1041
  res = JSON.parse(ctx.eval("JSON.stringify(read_res)"))
757
1042
  expect(res).to eq([
758
- page, page2
1043
+ page2
759
1044
  ])
760
- end
1045
+ end
761
1046
 
762
- it "Responds once to watch with a missing cache but where the pager responds before the disk" do
1047
+ it "Responds once to watch with a missing cache but where the pager responds before the disk for hash" do
763
1048
  ctx = flok_new_user File.read('./spec/kern/assets/vm/controller20.rb'), File.read("./spec/kern/assets/vm/config4.rb")
764
1049
 
765
1050
  ctx.eval %{
@@ -770,6 +1055,7 @@ it "vm_rehash_page can calculate the hash correctly" do
770
1055
  _head: null,
771
1056
  _next: null,
772
1057
  _id: "hello",
1058
+ _type: "hash",
773
1059
  entries: [
774
1060
  {_id: "hello2", _sig: "nohteunth"},
775
1061
  ]
@@ -781,6 +1067,7 @@ it "vm_rehash_page can calculate the hash correctly" do
781
1067
  _head: null,
782
1068
  _next: null,
783
1069
  _id: "hello",
1070
+ _type: "hash",
784
1071
  entries: [
785
1072
  {_id: "hello2", _sig: "nohteunth"},
786
1073
  {_id: "hello3", _sig: "athoeuntz"}