flok 0.0.103 → 0.0.105

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/drivers/chrome/config.yml +2 -0
  3. data/app/drivers/chrome/src/about.js +14 -0
  4. data/app/drivers/chrome/src/guid.js +9 -0
  5. data/app/drivers/chrome/src/net.js +25 -3
  6. data/app/kern/mod/about.js +19 -0
  7. data/app/kern/mod/hook.js +2 -2
  8. data/app/kern/mod/udid.js +9 -0
  9. data/app/kern/services/rest.rb +67 -8
  10. data/bin/flok +14 -0
  11. data/docs/mod/about.md +19 -0
  12. data/docs/mod/net.md +9 -4
  13. data/docs/mod/ui.md +1 -1
  14. data/docs/services/rest.md +24 -2
  15. data/docs/services/vm.md +4 -0
  16. data/docs/user_handbook/hooks.md +61 -5
  17. data/lib/flok/hooks_compiler.rb +6 -0
  18. data/lib/flok/user_compiler.rb +33 -5
  19. data/lib/flok/user_hook_generators/goto.rb +25 -3
  20. data/lib/flok/user_hook_generators/pop.rb +99 -0
  21. data/lib/flok/user_hook_generators/push.rb +119 -0
  22. data/lib/flok/version.rb +1 -1
  23. data/spec/iface/driver/about_spec.rb +14 -0
  24. data/spec/iface/driver/net_spec.rb +91 -2
  25. data/spec/iface/driver/ping_spec.rb +1 -0
  26. data/spec/kern/about_spec.rb +30 -0
  27. data/spec/kern/assets/hook_entry_points/controller0a_push.rb +31 -0
  28. data/spec/kern/assets/hook_entry_points/controller0b.rb +17 -0
  29. data/spec/kern/assets/hook_entry_points/controller0bc.rb +27 -0
  30. data/spec/kern/assets/hook_entry_points/controller_0b_pop.rb +18 -0
  31. data/spec/kern/assets/hook_entry_points/controller_0b_pop2.rb +66 -0
  32. data/spec/kern/assets/hook_entry_points/controller_0b_push.rb +15 -0
  33. data/spec/kern/assets/hook_entry_points/controller_0b_push2.rb +55 -0
  34. data/spec/kern/assets/rest_service/controller1b.rb +47 -0
  35. data/spec/kern/hook_entry_points_and_manifest_spec.rb +174 -0
  36. data/spec/kern/{hook_user_generators_spec.rb → hook_goto_user_generators_spec.rb} +145 -7
  37. data/spec/kern/hook_pop_user_generators_spec.rb +292 -0
  38. data/spec/kern/hook_push_user_generators_spec.rb +305 -0
  39. data/spec/kern/rest_service_spec.rb +97 -1
  40. data/spec/lib/helpers.rb +5 -3
  41. metadata +35 -5
  42. data/lib/flok/user_hook_generators/helpers.rb +0 -46
@@ -6,12 +6,15 @@ module Flok
6
6
  module HooksCompiler
7
7
  #Returns a new copy of the source transformed as described by the manifest
8
8
  def self.compile(src, manifest)
9
+ puts "a0"
9
10
  new_src = src.split("\n").map{|e| manifest.transform_line(e) }.join("\n")
10
11
 
11
12
  #Re-process macros
13
+ puts "a1"
12
14
  new_src = Flok.macro_process new_src
13
15
 
14
16
 
17
+ puts "a2"
15
18
  return new_src
16
19
  end
17
20
  end
@@ -28,13 +31,16 @@ module Flok
28
31
  #be inserted there, this will return the inserted code (which may then be multiple lines)
29
32
  #And will also remove the comment itself
30
33
  def transform_line line
34
+ puts "a3"
31
35
  #Get all the matched HooksManifestEntry(s)
32
36
  injected_code = @manifest_entries.select{|e| e.does_match? line}.map{|e| e.code_for_line(line)}
33
37
 
38
+ puts "an"
34
39
  #If there is a match of at least one hook, remove the original line and replace it
35
40
  #with all the newly found code from the HooksManifestEntry(s)
36
41
  return injected_code.join("\n") if injected_code.count > 0
37
42
 
43
+ puts "a4"
38
44
  #Else, nothing was found, keep moving along and don't transform the line
39
45
  return line
40
46
  end
@@ -184,12 +184,12 @@ module Flok
184
184
  __info__.action = "#{action_name}";
185
185
 
186
186
  var __free_asap = true;
187
- //HOOK_ENTRY[controller_will_goto] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "to_action" => action_name}.to_json}
187
+ //HOOK_ENTRY[controller_will_goto] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "to_action" => action_name, "handling_event_named" => @handling_event_named}.to_json}
188
188
 
189
189
  //If views are configured to not free right away, set up a new stack of views to free
190
190
  //This is usually picked up by the hook GOTO
191
191
  if (__free_asap === false) {
192
- var views_to_free_id = gen_id();
192
+ var views_to_free_id = tels(1);
193
193
  views_to_free[views_to_free_id] = views_to_free[views_to_free_id] || [];
194
194
  }
195
195
 
@@ -237,7 +237,7 @@ module Flok
237
237
  //located in ctable
238
238
  __info__.cte.actions[__info__.action].on_entry(__base__)
239
239
 
240
- //HOOK_ENTRY[controller_did_goto] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "to_action" => action_name}.to_json}
240
+ //HOOK_ENTRY[controller_did_goto] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "to_action" => action_name, "handling_event_named" => @handling_event_named}.to_json}
241
241
  //'choose_action' pseudo-action will be sent as 'null' as it's the initial state
242
242
  if (old_action === "choose_action") {
243
243
  old_action = null;
@@ -269,6 +269,9 @@ module Flok
269
269
 
270
270
  __info__.action = "#{action_name}";
271
271
 
272
+ //HOOK_ENTRY[controller_will_push] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "to_action" => action_name, "handling_event_named" => @handling_event_named}.to_json}
273
+
274
+
272
275
  //Prep embeds array, embeds[0] refers to the spot bp+2 (bp is vc, bp+1 is main)
273
276
  __info__.embeds = [];
274
277
  for (var i = 1; i < #{@controller.spots.count}; ++i) {
@@ -279,6 +282,8 @@ module Flok
279
282
  //located in ctable
280
283
  __info__.cte.actions[__info__.action].on_entry(__base__)
281
284
 
285
+ //HOOK_ENTRY[controller_did_push] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "to_action" => action_name, "handling_event_named" => @handling_event_named}.to_json}
286
+
282
287
  //Send off event for action change
283
288
  main_q.push([3, "if_event", __base__, "action", {
284
289
  from: old_action,
@@ -303,6 +308,16 @@ module Flok
303
308
  //Save the old action
304
309
  //var old_action = __info__.action;
305
310
 
311
+ var __free_asap = true;
312
+ //HOOK_ENTRY[controller_will_pop] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "handling_event_named" => @handling_event_named}.to_json}
313
+
314
+ //If views are configured to not free right away, set up a new stack of views to free
315
+ //This is usually picked up by the hook GOTO
316
+ if (__free_asap === false) {
317
+ var views_to_free_id = tels(1);
318
+ views_to_free[views_to_free_id] = views_to_free[views_to_free_id] || [];
319
+ }
320
+
306
321
  //Restore the action we pushed from
307
322
  __info__.action = orig_action;
308
323
 
@@ -312,7 +327,12 @@ module Flok
312
327
  for (var i = 0; i < __info__.embeds.length; ++i) {
313
328
  for (var j = 0; j < __info__.embeds[i].length; ++j) {
314
329
  //Free +1 because that will be the 'main' view
315
- main_q.push([1, "if_free_view", embeds[i][j]+1]);
330
+ //Free if 'free_asap' is not set, this is usually configured via the 'goto' hook
331
+ if (__free_asap === true) {
332
+ main_q.push([1, "if_free_view", embeds[i][j]+1]);
333
+ } else {
334
+ views_to_free[views_to_free_id].push(embeds[i][j]+1);
335
+ }
316
336
 
317
337
  //Call dealloc on the controller
318
338
  tel_deref(embeds[i][j]).cte.__dealloc__(embeds[i][j]);
@@ -321,6 +341,9 @@ module Flok
321
341
 
322
342
  //Restore embeds
323
343
  __info__.embeds = orig_embeds;
344
+
345
+ //HOOK_ENTRY[controller_did_pop] #{{"controller_name" => @controller.name, "might_respond_to" => @ctx.might_respond_to, "actions_responds_to" => @ctx.actions_respond_to, "from_action" => @name, "handling_event_named" => @handling_event_named}.to_json}
346
+
324
347
  }
325
348
 
326
349
  out.puts res
@@ -580,7 +603,12 @@ module Flok
580
603
  #prior-knowledge of controller-level information like all possible events in all actions for hooks
581
604
  unless @__ons_did_build
582
605
  @__ons_did_build = true
583
- @__ons = @_ons.map{|e| {:name => e[:name], :src => _macro(e[:src])}}
606
+ @__ons = @_ons.map do |e|
607
+ @handling_event_named = e[:name]
608
+ src = _macro(e[:src])
609
+ @handling_event_named = nil
610
+ {:name => e[:name], :src => src}
611
+ end
584
612
  end
585
613
 
586
614
  @__ons_is_building = false
@@ -1,5 +1,3 @@
1
- require_relative 'helpers'
2
-
3
1
  module Flok
4
2
  class GotoHooksDSLEnv
5
3
  attr_accessor :selectors, :before_view_spider, :after_view_spider
@@ -34,6 +32,13 @@ module Flok
34
32
  end
35
33
  end
36
34
 
35
+ def triggered_by event_name
36
+ @selectors << lambda do |params|
37
+ handling_event_named = params["handling_event_named"]
38
+ next handling_event_named == event_name
39
+ end
40
+ end
41
+
37
42
  def to_action_responds_to? responds
38
43
  @selectors << lambda do |params|
39
44
  to_action = params["to_action"]
@@ -51,6 +56,23 @@ module Flok
51
56
  next false
52
57
  end
53
58
  end
59
+
60
+ def to_action *names
61
+ @selectors << lambda do |params|
62
+ to_action = params["to_action"]
63
+
64
+ next names.include? to_action
65
+ end
66
+ end
67
+
68
+ def from_action *names
69
+ @selectors << lambda do |params|
70
+ from_action = params["from_action"]
71
+
72
+ next names.include? from_action
73
+ end
74
+ end
75
+
54
76
  #################################################################################
55
77
 
56
78
  def before_views spider
@@ -85,7 +107,7 @@ module Flok
85
107
  manifest << HooksManifestEntry.new("controller_did_goto", dsl_env.selectors) do |entry_hook_params|
86
108
  next %{
87
109
  //The completion callback will share a pointer to the views_to_free key index
88
- reg_evt(views_to_free_id, hook_goto_completion_cb);
110
+ reg_evt(views_to_free_id, hook_completion_cb);
89
111
 
90
112
  var #{ns}_after_views = find_view(__base__, #{dsl_env.after_view_spider.to_json});
91
113
  var #{ns}_info = {
@@ -0,0 +1,99 @@
1
+ module Flok
2
+ class PopHooksDSLEnv
3
+ attr_accessor :selectors, :before_view_spider, :after_view_spider
4
+
5
+ def initialize
6
+ @selectors = []
7
+ @before_view_spider = {}
8
+ @after_view_spider = {}
9
+ end
10
+
11
+ def controller name
12
+ @selectors << ->(p) { p["controller_name"] and p["controller_name"] == name.to_s }
13
+ end
14
+
15
+ #The previous / next action contains an event handler for...
16
+ #################################################################################
17
+ def from_action_responds_to? responds
18
+ @selectors << lambda do |params|
19
+ from_action = params["from_action"]
20
+ actions_respond_to = params["actions_responds_to"] #This is a hash that maps all actions to sensetivity lists
21
+
22
+ #Get the sensetivity list if possible for this action (this is the list of events this action responds to)
23
+ if actions_respond_to[from_action]
24
+ sensetivity_list = actions_respond_to[from_action]
25
+
26
+ #Does the sensetivity list include the event we are interested in?
27
+ next sensetivity_list.include? responds
28
+ end
29
+
30
+ #The action wasn't even listed on the list, i.e. it has no sensetivity list
31
+ next false
32
+ end
33
+ end
34
+
35
+ def from_action *names
36
+ @selectors << lambda do |params|
37
+ from_action = params["from_action"]
38
+
39
+ next names.include? from_action
40
+ end
41
+ end
42
+
43
+ def triggered_by event_name
44
+ @selectors << lambda do |params|
45
+ handling_event_named = params["handling_event_named"]
46
+ next handling_event_named == event_name
47
+ end
48
+ end
49
+
50
+
51
+ #################################################################################
52
+
53
+ def before_views spider
54
+ @before_view_spider = spider
55
+ end
56
+
57
+ def after_views spider
58
+ @after_view_spider = spider
59
+ end
60
+ end
61
+
62
+ UserHooksToManifestOrchestrator.register_hook_gen :pop do |manifest, params|
63
+ hook_event_name = params[:hook_event_name]
64
+
65
+ #Evaluate User given DSL (params[:block]) which comes from `./confg/hooks.rb`
66
+ #to retrieve a set of selectors which we will pass the hooks compiler
67
+ block = params[:block]
68
+ dsl_env = PopHooksDSLEnv.new
69
+ dsl_env.instance_eval(&block)
70
+
71
+ ns = "_#{SecureRandom.hex[0..5]}"
72
+
73
+ #Inject into HOOK_ENTRY[controller_will_pop] that match the given selectors from the DSL
74
+ #based on the hook entry static parameters
75
+ manifest << HooksManifestEntry.new("controller_will_pop", dsl_env.selectors) do |entry_hook_params|
76
+ next %{
77
+ var #{ns}_before_views = find_view(__base__, #{dsl_env.before_view_spider.to_json});
78
+ __free_asap = false;
79
+ }
80
+ end
81
+
82
+ manifest << HooksManifestEntry.new("controller_did_pop", dsl_env.selectors) do |entry_hook_params|
83
+ next %{
84
+ //The completion callback will share a pointer to the views_to_free key index
85
+ reg_evt(views_to_free_id, hook_completion_cb);
86
+
87
+ var #{ns}_after_views = find_view(__base__, #{dsl_env.after_view_spider.to_json});
88
+ var #{ns}_info = {
89
+ views: #{ns}_after_views,
90
+ cep: views_to_free_id
91
+ };
92
+ for (var k in #{ns}_before_views) {
93
+ #{ns}_info.views[k] = #{ns}_before_views[k];
94
+ }
95
+ SEND("main", "if_hook_event", "#{hook_event_name}", #{ns}_info);
96
+ }
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,119 @@
1
+ module Flok
2
+ class PushHooksDSLEnv
3
+ attr_accessor :selectors, :before_view_spider, :after_view_spider
4
+
5
+ def initialize
6
+ @selectors = []
7
+ @before_view_spider = {}
8
+ @after_view_spider = {}
9
+ end
10
+
11
+ def controller name
12
+ @selectors << ->(p) { p["controller_name"] and p["controller_name"] == name.to_s }
13
+ end
14
+
15
+ #The previous / next action contains an event handler for...
16
+ #################################################################################
17
+ def from_action_responds_to? responds
18
+ @selectors << lambda do |params|
19
+ from_action = params["from_action"]
20
+ actions_respond_to = params["actions_responds_to"] #This is a hash that maps all actions to sensetivity lists
21
+
22
+ #Get the sensetivity list if possible for this action (this is the list of events this action responds to)
23
+ if actions_respond_to[from_action]
24
+ sensetivity_list = actions_respond_to[from_action]
25
+
26
+ #Does the sensetivity list include the event we are interested in?
27
+ next sensetivity_list.include? responds
28
+ end
29
+
30
+ #The action wasn't even listed on the list, i.e. it has no sensetivity list
31
+ next false
32
+ end
33
+ end
34
+
35
+ def to_action_responds_to? responds
36
+ @selectors << lambda do |params|
37
+ to_action = params["to_action"]
38
+ actions_respond_to = params["actions_responds_to"] #This is a hash that maps all actions to sensetivity lists
39
+
40
+ #Get the sensetivity list if possible for this action (this is the list of events this action responds to)
41
+ if actions_respond_to[to_action]
42
+ sensetivity_list = actions_respond_to[to_action]
43
+
44
+ #Does the sensetivity list include the event we are interested in?
45
+ next sensetivity_list.include? responds
46
+ end
47
+
48
+ #The action wasn't even listed on the list, i.e. it has no sensetivity list
49
+ next false
50
+ end
51
+ end
52
+
53
+ def to_action *names
54
+ @selectors << lambda do |params|
55
+ to_action = params["to_action"]
56
+
57
+ next names.include? to_action
58
+ end
59
+ end
60
+
61
+ def from_action *names
62
+ @selectors << lambda do |params|
63
+ from_action = params["from_action"]
64
+
65
+ next names.include? from_action
66
+ end
67
+ end
68
+
69
+ def triggered_by event_name
70
+ @selectors << lambda do |params|
71
+ handling_event_named = params["handling_event_named"]
72
+ next handling_event_named == event_name
73
+ end
74
+ end
75
+
76
+ #################################################################################
77
+
78
+ def before_views spider
79
+ @before_view_spider = spider
80
+ end
81
+
82
+ def after_views spider
83
+ @after_view_spider = spider
84
+ end
85
+ end
86
+
87
+ UserHooksToManifestOrchestrator.register_hook_gen :push do |manifest, params|
88
+ hook_event_name = params[:hook_event_name]
89
+
90
+ #Evaluate User given DSL (params[:block]) which comes from `./confg/hooks.rb`
91
+ #to retrieve a set of selectors which we will pass the hooks compiler
92
+ block = params[:block]
93
+ dsl_env = PushHooksDSLEnv.new
94
+ dsl_env.instance_eval(&block)
95
+
96
+ ns = "_#{SecureRandom.hex[0..5]}"
97
+
98
+ #Inject into HOOK_ENTRY[controller_will_push] that match the given selectors from the DSL
99
+ #based on the hook entry static parameters
100
+ manifest << HooksManifestEntry.new("controller_will_push", dsl_env.selectors) do |entry_hook_params|
101
+ next %{
102
+ var #{ns}_before_views = find_view(__base__, #{dsl_env.before_view_spider.to_json});
103
+ }
104
+ end
105
+
106
+ manifest << HooksManifestEntry.new("controller_did_push", dsl_env.selectors) do |entry_hook_params|
107
+ next %{
108
+ var #{ns}_after_views = find_view(__base__, #{dsl_env.after_view_spider.to_json});
109
+ var #{ns}_info = {
110
+ views: #{ns}_after_views
111
+ };
112
+ for (var k in #{ns}_before_views) {
113
+ #{ns}_info.views[k] = #{ns}_before_views[k];
114
+ }
115
+ SEND("main", "if_hook_event", "#{hook_event_name}", #{ns}_info);
116
+ }
117
+ end
118
+ end
119
+ end
@@ -1,3 +1,3 @@
1
1
  module Flok
2
- VERSION = "0.0.103"
2
+ VERSION = "0.0.105"
3
3
  end
@@ -0,0 +1,14 @@
1
+ Dir.chdir File.join File.dirname(__FILE__), '../../../'
2
+ require './spec/env/iface.rb'
3
+
4
+ RSpec.describe "iface:driver:about" do
5
+ include_context "iface:driver"
6
+
7
+ it "supports about" do
8
+ @pipe.puts [[0, 0, "if_about_poll"]].to_json
9
+ res = @pipe.readline
10
+ expect(res["platform"].class).to eq(String)
11
+ expect(res["language"].class).to eq(String)
12
+ expect(res["udid"].class).to eq(String)
13
+ end
14
+ end
@@ -65,7 +65,7 @@ RSpec.describe "iface:driver:net" do
65
65
  @ptr = rand(9999999)
66
66
  @pipe.puts [[1, 4, "if_net_req", "GET", "http://127.0.0.1:#{web.port}", {'secret' => @secret}, @ptr]].to_json
67
67
 
68
- res = [3, "int_net_cb", @ptr, true, @secret2msg]
68
+ res = [3, "int_net_cb", @ptr, 200, @secret2msg]
69
69
  expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
70
70
  ensure
71
71
  web.kill
@@ -80,10 +80,99 @@ RSpec.describe "iface:driver:net" do
80
80
  matcher = proc do |x|
81
81
  x = JSON.parse(x)
82
82
  a = ->(e){e.class == String && e.length > 0} #Error message should be a string that's not blank
83
- expect(x).to look_like [3, "int_net_cb", @ptr, false, a]
83
+ expect(x).to look_like [3, "int_net_cb", @ptr, -1, a]
84
84
  true
85
85
  end
86
86
 
87
87
  expect(@pipe).to readline_and_equal_proc_x_within_y_seconds(matcher, 5.seconds)
88
88
  end
89
+
90
+ it "Can call a network request with headers" do
91
+ begin
92
+ web = Webbing.get "/" do |params, headers|
93
+ expect(headers["content-type"]).to eq("json")
94
+ @hit = true
95
+ {}
96
+ end
97
+
98
+ @ptr = rand(9999999)
99
+ @pipe.puts [[1, 5, "if_net_req2", "GET", {"content-type" => "json"}, "http://127.0.0.1:#{web.port}", {}, @ptr]].to_json
100
+
101
+
102
+ #Wait for response
103
+ @pipe.puts [[0, 0, "ping"]].to_json; @pipe.readline_timeout
104
+ sleep 1
105
+
106
+ expect(@hit).to eq(true)
107
+ ensure
108
+ web.kill
109
+ end
110
+ end
111
+
112
+
113
+ it "Can call a network request with parameters and a header" do
114
+ begin
115
+ @secret = SecureRandom.hex
116
+ web = Webbing.get "/" do |params, headers|
117
+ @headers = headers
118
+ @rcv_secret = params['secret']
119
+ {}
120
+ end
121
+
122
+ @ptr = rand(9999999)
123
+ @pipe.puts [[1, 5, "if_net_req2", "GET", {"content-type" => "blah"}, "http://127.0.0.1:#{web.port}", {'secret' => @secret}, @ptr]].to_json
124
+
125
+ #Wait for response
126
+ @pipe.puts [[0, 0, "ping"]].to_json; @pipe.readline_timeout
127
+ sleep 2
128
+
129
+ expect(@rcv_secret).to eq(@secret)
130
+ expect(@headers["content-type"]).to eq(["blah"])
131
+ ensure
132
+ web.kill
133
+ end
134
+ end
135
+
136
+
137
+ it "Does send a network interupt int_net_cb with success and the correct payload with headers" do
138
+ begin
139
+ @secret = SecureRandom.hex
140
+ @secret2 = SecureRandom.hex
141
+ @secret2msg = {"secret2" => @secret2}
142
+ web = Webbing.get "/" do |params, headers|
143
+ $stderr.puts headers
144
+ expect(headers["content-type"]).to eq("json")
145
+ @rcv_secret = params['secret']
146
+
147
+ @secret2msg
148
+ end
149
+
150
+ #Wait for response
151
+ @ptr = rand(9999999)
152
+ @pipe.puts [[1, 5, "if_net_req2", "GET", {"content-type" => "json"}, "http://127.0.0.1:#{web.port}", {'secret' => @secret}, @ptr]].to_json
153
+
154
+ res = [3, "int_net_cb", @ptr, 200, @secret2msg]
155
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
156
+ ensure
157
+ web.kill
158
+ end
159
+ end
160
+
161
+
162
+ it "Does send a network interupt int_net_cb with error and the correct payload and headers" do
163
+ #Wait for response
164
+ @ptr = rand(9999999)
165
+ @pipe.puts [[1, 5, "if_net_req2", "GET", {}, "http://no_such_url#{SecureRandom.hex}.com", {}, @ptr]].to_json
166
+
167
+ matcher = proc do |x|
168
+ x = JSON.parse(x)
169
+ a = ->(e){e.class == String && e.length > 0} #Error message should be a string that's not blank
170
+ expect(x).to look_like [3, "int_net_cb", @ptr, -1, a]
171
+ true
172
+ end
173
+
174
+ expect(@pipe).to readline_and_equal_proc_x_within_y_seconds(matcher, 5.seconds)
175
+ end
176
+
177
+
89
178
  end