MuranoCLI 2.0.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 (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +27 -0
  6. data/LICENSE.txt +19 -0
  7. data/MuranoCLI.gemspec +50 -0
  8. data/MuranoCLI.iss +50 -0
  9. data/README.markdown +208 -0
  10. data/Rakefile +188 -0
  11. data/TODO.taskpaper +122 -0
  12. data/bin/mr +8 -0
  13. data/bin/murano +84 -0
  14. data/docs/demo.md +109 -0
  15. data/lib/MrMurano/Account.rb +211 -0
  16. data/lib/MrMurano/Config-Migrate.rb +47 -0
  17. data/lib/MrMurano/Config.rb +286 -0
  18. data/lib/MrMurano/Mock.rb +63 -0
  19. data/lib/MrMurano/Product-1P-Device.rb +145 -0
  20. data/lib/MrMurano/Product-Resources.rb +195 -0
  21. data/lib/MrMurano/Product.rb +358 -0
  22. data/lib/MrMurano/ProjectFile.rb +349 -0
  23. data/lib/MrMurano/Solution-Cors.rb +46 -0
  24. data/lib/MrMurano/Solution-Endpoint.rb +177 -0
  25. data/lib/MrMurano/Solution-File.rb +150 -0
  26. data/lib/MrMurano/Solution-ServiceConfig.rb +140 -0
  27. data/lib/MrMurano/Solution-Services.rb +326 -0
  28. data/lib/MrMurano/Solution-Users.rb +129 -0
  29. data/lib/MrMurano/Solution.rb +59 -0
  30. data/lib/MrMurano/SubCmdGroupContext.rb +49 -0
  31. data/lib/MrMurano/SyncUpDown.rb +565 -0
  32. data/lib/MrMurano/commands/assign.rb +57 -0
  33. data/lib/MrMurano/commands/businessList.rb +45 -0
  34. data/lib/MrMurano/commands/completion.rb +152 -0
  35. data/lib/MrMurano/commands/config.rb +67 -0
  36. data/lib/MrMurano/commands/content.rb +130 -0
  37. data/lib/MrMurano/commands/cors.rb +30 -0
  38. data/lib/MrMurano/commands/domain.rb +17 -0
  39. data/lib/MrMurano/commands/gb.rb +33 -0
  40. data/lib/MrMurano/commands/init.rb +138 -0
  41. data/lib/MrMurano/commands/keystore.rb +157 -0
  42. data/lib/MrMurano/commands/logs.rb +78 -0
  43. data/lib/MrMurano/commands/mock.rb +63 -0
  44. data/lib/MrMurano/commands/password.rb +88 -0
  45. data/lib/MrMurano/commands/postgresql.rb +41 -0
  46. data/lib/MrMurano/commands/product.rb +14 -0
  47. data/lib/MrMurano/commands/productCreate.rb +39 -0
  48. data/lib/MrMurano/commands/productDelete.rb +33 -0
  49. data/lib/MrMurano/commands/productDevice.rb +84 -0
  50. data/lib/MrMurano/commands/productDeviceIdCmds.rb +86 -0
  51. data/lib/MrMurano/commands/productList.rb +45 -0
  52. data/lib/MrMurano/commands/productWrite.rb +27 -0
  53. data/lib/MrMurano/commands/show.rb +80 -0
  54. data/lib/MrMurano/commands/solution.rb +14 -0
  55. data/lib/MrMurano/commands/solutionCreate.rb +39 -0
  56. data/lib/MrMurano/commands/solutionDelete.rb +34 -0
  57. data/lib/MrMurano/commands/solutionList.rb +45 -0
  58. data/lib/MrMurano/commands/status.rb +92 -0
  59. data/lib/MrMurano/commands/sync.rb +60 -0
  60. data/lib/MrMurano/commands/timeseries.rb +115 -0
  61. data/lib/MrMurano/commands/tsdb.rb +271 -0
  62. data/lib/MrMurano/commands/usage.rb +23 -0
  63. data/lib/MrMurano/commands/zshcomplete.erb +112 -0
  64. data/lib/MrMurano/commands.rb +32 -0
  65. data/lib/MrMurano/hash.rb +20 -0
  66. data/lib/MrMurano/http.rb +153 -0
  67. data/lib/MrMurano/makePretty.rb +75 -0
  68. data/lib/MrMurano/schema/pf-v1.0.0.yaml +114 -0
  69. data/lib/MrMurano/schema/sf-v0.2.0.yaml +77 -0
  70. data/lib/MrMurano/schema/sf-v0.3.0.yaml +78 -0
  71. data/lib/MrMurano/template/mock.erb +9 -0
  72. data/lib/MrMurano/template/projectFile.murano.erb +81 -0
  73. data/lib/MrMurano/verbosing.rb +99 -0
  74. data/lib/MrMurano/version.rb +4 -0
  75. data/lib/MrMurano.rb +20 -0
  76. data/spec/Account-Passwords_spec.rb +242 -0
  77. data/spec/Account_spec.rb +272 -0
  78. data/spec/ConfigFile_spec.rb +50 -0
  79. data/spec/ConfigMigrate_spec.rb +89 -0
  80. data/spec/Config_spec.rb +409 -0
  81. data/spec/Http_spec.rb +204 -0
  82. data/spec/MakePretties_spec.rb +118 -0
  83. data/spec/Mock_spec.rb +53 -0
  84. data/spec/ProductBase_spec.rb +113 -0
  85. data/spec/ProductContent_spec.rb +162 -0
  86. data/spec/ProductResources_spec.rb +329 -0
  87. data/spec/Product_1P_Device_spec.rb +202 -0
  88. data/spec/Product_1P_RPC_spec.rb +175 -0
  89. data/spec/Product_spec.rb +153 -0
  90. data/spec/ProjectFile_spec.rb +324 -0
  91. data/spec/Solution-Cors_spec.rb +164 -0
  92. data/spec/Solution-Endpoint_spec.rb +581 -0
  93. data/spec/Solution-File_spec.rb +212 -0
  94. data/spec/Solution-ServiceConfig_spec.rb +202 -0
  95. data/spec/Solution-ServiceDevice_spec.rb +176 -0
  96. data/spec/Solution-ServiceEventHandler_spec.rb +385 -0
  97. data/spec/Solution-ServiceModules_spec.rb +465 -0
  98. data/spec/Solution-UsersRoles_spec.rb +207 -0
  99. data/spec/Solution_spec.rb +92 -0
  100. data/spec/SyncRoot_spec.rb +83 -0
  101. data/spec/SyncUpDown_spec.rb +495 -0
  102. data/spec/Verbosing_spec.rb +279 -0
  103. data/spec/_workspace.rb +27 -0
  104. data/spec/cmd_assign_spec.rb +51 -0
  105. data/spec/cmd_business_spec.rb +59 -0
  106. data/spec/cmd_common.rb +72 -0
  107. data/spec/cmd_config_spec.rb +68 -0
  108. data/spec/cmd_content_spec.rb +71 -0
  109. data/spec/cmd_cors_spec.rb +50 -0
  110. data/spec/cmd_device_spec.rb +96 -0
  111. data/spec/cmd_domain_spec.rb +32 -0
  112. data/spec/cmd_init_spec.rb +30 -0
  113. data/spec/cmd_keystore_spec.rb +97 -0
  114. data/spec/cmd_password_spec.rb +62 -0
  115. data/spec/cmd_status_spec.rb +239 -0
  116. data/spec/cmd_syncdown_spec.rb +86 -0
  117. data/spec/cmd_syncup_spec.rb +62 -0
  118. data/spec/cmd_usage_spec.rb +36 -0
  119. data/spec/fixtures/.mrmuranorc +9 -0
  120. data/spec/fixtures/ProjectFiles/invalid.yaml +9 -0
  121. data/spec/fixtures/ProjectFiles/only_meta.yaml +24 -0
  122. data/spec/fixtures/ProjectFiles/with_routes.yaml +27 -0
  123. data/spec/fixtures/SolutionFiles/0.2.0.json +20 -0
  124. data/spec/fixtures/SolutionFiles/0.2.0_invalid.json +18 -0
  125. data/spec/fixtures/SolutionFiles/0.2.json +21 -0
  126. data/spec/fixtures/SolutionFiles/0.3.0.json +20 -0
  127. data/spec/fixtures/SolutionFiles/0.3.0_invalid.json +19 -0
  128. data/spec/fixtures/SolutionFiles/0.3.json +20 -0
  129. data/spec/fixtures/SolutionFiles/basic.json +20 -0
  130. data/spec/fixtures/SolutionFiles/secret.json +6 -0
  131. data/spec/fixtures/configfile +9 -0
  132. data/spec/fixtures/dumped_config +42 -0
  133. data/spec/fixtures/mrmuranorc_deleted_bob +8 -0
  134. data/spec/fixtures/mrmuranorc_tool_bob +3 -0
  135. data/spec/fixtures/product_spec_files/example.exoline.spec.yaml +116 -0
  136. data/spec/fixtures/product_spec_files/example.murano.spec.yaml +14 -0
  137. data/spec/fixtures/product_spec_files/gwe.exoline.spec.yaml +21 -0
  138. data/spec/fixtures/product_spec_files/gwe.murano.spec.yaml +16 -0
  139. data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
  140. data/spec/fixtures/product_spec_files/lightbulb.yaml +14 -0
  141. data/spec/fixtures/roles-three.yaml +11 -0
  142. data/spec/fixtures/syncable_content/assets/icon.png +0 -0
  143. data/spec/fixtures/syncable_content/assets/index.html +0 -0
  144. data/spec/fixtures/syncable_content/assets/js/script.js +0 -0
  145. data/spec/fixtures/syncable_content/modules/table_util.lua +58 -0
  146. data/spec/fixtures/syncable_content/routes/manyRoutes.lua +11 -0
  147. data/spec/fixtures/syncable_content/routes/singleRoute.lua +5 -0
  148. data/spec/fixtures/syncable_content/services/devdata.lua +18 -0
  149. data/spec/fixtures/syncable_content/services/timers.lua +4 -0
  150. data/spec/spec_helper.rb +119 -0
  151. metadata +498 -0
@@ -0,0 +1,385 @@
1
+ require 'MrMurano/version'
2
+ require 'MrMurano/Solution-Services'
3
+ require 'tempfile'
4
+ require '_workspace'
5
+
6
+ RSpec.describe MrMurano::EventHandler do
7
+ include_context "WORKSPACE"
8
+ before(:example) do
9
+ $cfg = MrMurano::Config.new
10
+ $cfg.load
11
+ $project = MrMurano::ProjectFile.new
12
+ $project.load
13
+ $cfg['net.host'] = 'bizapi.hosted.exosite.io'
14
+ $cfg['solution.id'] = 'XYZ'
15
+
16
+ @srv = MrMurano::EventHandler.new
17
+ allow(@srv).to receive(:token).and_return("TTTTTTTTTT")
18
+ end
19
+
20
+ it "initializes" do
21
+ uri = @srv.endPoint('/')
22
+ expect(uri.to_s).to eq("https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/")
23
+ end
24
+
25
+ it "lists" do
26
+ body = {:items=>[{:id=>"9K0",
27
+ :name=>"debug",
28
+ :alias=>"XYZ_debug",
29
+ :solution_id=>"XYZ",
30
+ :service=>"device",
31
+ :event=>"datapoint",
32
+ :created_at=>"2016-07-07T19:16:19.479Z",
33
+ :updated_at=>"2016-09-12T13:26:55.868Z"}],
34
+ :total=>1}
35
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler").
36
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
37
+ 'Content-Type'=>'application/json'}).
38
+ to_return(body: body.to_json)
39
+
40
+ ret = @srv.list()
41
+ expect(ret).to eq(body[:items])
42
+ end
43
+
44
+ it "fetches, with header" do
45
+ body = {:id=>"9K0",
46
+ :name=>"debug",
47
+ :alias=>"XYZ_debug",
48
+ :solution_id=>"XYZ",
49
+ :service=>"device",
50
+ :event=>"datapoint",
51
+ :created_at=>"2016-07-07T19:16:19.479Z",
52
+ :updated_at=>"2016-09-12T13:26:55.868Z",
53
+ :script=>%{--#EVENT device datapoint
54
+ -- lua code is here
55
+ function foo(bar)
56
+ return bar + 1
57
+ end
58
+ }
59
+ }
60
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/9K0").
61
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
62
+ 'Content-Type'=>'application/json'}).
63
+ to_return(body: body.to_json)
64
+
65
+ ret = @srv.fetch('9K0')
66
+ expect(ret).to eq(body[:script])
67
+ end
68
+
69
+ it "fetches, with header into block" do
70
+ body = {:id=>"9K0",
71
+ :name=>"debug",
72
+ :alias=>"XYZ_debug",
73
+ :solution_id=>"XYZ",
74
+ :service=>"device",
75
+ :event=>"datapoint",
76
+ :created_at=>"2016-07-07T19:16:19.479Z",
77
+ :updated_at=>"2016-09-12T13:26:55.868Z",
78
+ :script=>%{--#EVENT device datapoint
79
+ -- lua code is here
80
+ function foo(bar)
81
+ return bar + 1
82
+ end
83
+ }
84
+ }
85
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/9K0").
86
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
87
+ 'Content-Type'=>'application/json'}).
88
+ to_return(body: body.to_json)
89
+
90
+ ret = nil
91
+ @srv.fetch('9K0') { |sc| ret = sc }
92
+ expect(ret).to eq(body[:script])
93
+ end
94
+
95
+ it "fetches, without header" do
96
+ body = {:id=>"9K0",
97
+ :name=>"debug",
98
+ :alias=>"XYZ_debug",
99
+ :solution_id=>"XYZ",
100
+ :service=>"device",
101
+ :event=>"datapoint",
102
+ :created_at=>"2016-07-07T19:16:19.479Z",
103
+ :updated_at=>"2016-09-12T13:26:55.868Z",
104
+ :script=>%{-- lua code is here
105
+ function foo(bar)
106
+ return bar + 1
107
+ end
108
+ }
109
+ }
110
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/9K0").
111
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
112
+ 'Content-Type'=>'application/json'}).
113
+ to_return(body: body.to_json)
114
+
115
+ ret = @srv.fetch('9K0')
116
+ expect(ret).to eq(%{--#EVENT device datapoint
117
+ -- lua code is here
118
+ function foo(bar)
119
+ return bar + 1
120
+ end
121
+ })
122
+ end
123
+
124
+ it "removes" do
125
+ stub_request(:delete, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/9K0").
126
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
127
+ 'Content-Type'=>'application/json'}).
128
+ to_return(body: "")
129
+
130
+ ret = @srv.remove('9K0')
131
+ expect(ret).to eq({})
132
+ end
133
+
134
+ it "uploads over old version" do
135
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/XYZ_data_datapoint").
136
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
137
+ 'Content-Type'=>'application/json'}).
138
+ to_return(body: "")
139
+
140
+ Tempfile.open('foo') do |tio|
141
+ tio << %{-- lua code is here
142
+ function foo(bar)
143
+ return bar + 1
144
+ end
145
+ }
146
+ tio.close
147
+
148
+ ret = @srv.upload(tio.path, {:id=>"9K0",
149
+ :service=>'data',
150
+ :event=>'datapoint',
151
+ :solution_id=>"XYZ",
152
+ })
153
+ expect(ret)
154
+ end
155
+ end
156
+
157
+ it "uploads when nothing is there" do
158
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/XYZ_device_datapoint").
159
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
160
+ 'Content-Type'=>'application/json'}).
161
+ to_return(status: 404)
162
+ stub_request(:post, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/eventhandler/").
163
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
164
+ 'Content-Type'=>'application/json'}).
165
+ to_return(body: "")
166
+
167
+ Tempfile.open('foo') do |tio|
168
+ tio << %{-- lua code is here
169
+ function foo(bar)
170
+ return bar + 1
171
+ end
172
+ }
173
+ tio.close
174
+
175
+ ret = @srv.upload(tio.path, {:id=>"9K0",
176
+ :solution_id=>"XYZ",
177
+ :service=>"device",
178
+ :event=>"datapoint",
179
+ })
180
+ expect(ret)
181
+ end
182
+
183
+ end
184
+
185
+ context "compares" do
186
+ before(:example) do
187
+ @iA = {:id=>"9K0",
188
+ :name=>"debug",
189
+ :alias=>"XYZ_debug",
190
+ :solution_id=>"XYZ",
191
+ :service=>"device",
192
+ :event=>"datapoint",
193
+ :created_at=>"2016-07-07T19:16:19.479Z",
194
+ :updated_at=>"2016-09-12T13:26:55.868Z"}
195
+ @iB = {:id=>"9K0",
196
+ :name=>"debug",
197
+ :alias=>"XYZ_debug",
198
+ :solution_id=>"XYZ",
199
+ :service=>"device",
200
+ :event=>"datapoint",
201
+ :created_at=>"2016-07-07T19:16:19.479Z",
202
+ :updated_at=>"2016-09-12T13:26:55.868Z"}
203
+ end
204
+ it "both have updated_at" do
205
+ ret = @srv.docmp(@iA, @iB)
206
+ expect(ret).to eq(false)
207
+ end
208
+
209
+ it "iA is a local file" do
210
+ Tempfile.open('foo') do |tio|
211
+ tio << "something"
212
+ tio.close
213
+ iA = @iA.reject{|k,v| k == :updated_at}.merge({
214
+ :local_path => Pathname.new(tio.path)
215
+ })
216
+ ret = @srv.docmp(iA, @iB)
217
+ expect(ret).to eq(true)
218
+
219
+ iB = @iB.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
220
+ ret = @srv.docmp(iA, iB)
221
+ expect(ret).to eq(false)
222
+ end
223
+ end
224
+
225
+ it "iB is a local file" do
226
+ Tempfile.open('foo') do |tio|
227
+ tio << "something"
228
+ tio.close
229
+ iB = @iB.reject{|k,v| k == :updated_at}.merge({
230
+ :local_path => Pathname.new(tio.path)
231
+ })
232
+ ret = @srv.docmp(@iA, iB)
233
+ expect(ret).to eq(true)
234
+
235
+ iA = @iA.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
236
+ ret = @srv.docmp(iA, iB)
237
+ expect(ret).to eq(false)
238
+ end
239
+ end
240
+ end
241
+
242
+ context "Lookup functions" do
243
+ it "gets local name" do
244
+ ret = @srv.tolocalname({ :name=>"bob" }, nil)
245
+ expect(ret).to eq('bob.lua')
246
+ end
247
+
248
+ it "gets synckey" do
249
+ ret = @srv.synckey({ :service=>'device', :event=>'datapoint' })
250
+ expect(ret).to eq("device_datapoint")
251
+ end
252
+
253
+ it "gets searchfor" do
254
+ $cfg['eventhandler.searchFor'] = %{a b c/**/d/*.bob}
255
+ ret = @srv.searchFor
256
+ expect(ret).to eq(["a", "b", "c/**/d/*.bob"])
257
+ end
258
+
259
+ it "gets ignoring" do
260
+ $cfg['eventhandler.ignoring'] = %{a b c/**/d/*.bob}
261
+ ret = @srv.ignoring
262
+ expect(ret).to eq(["a", "b", "c/**/d/*.bob"])
263
+ end
264
+
265
+ it "raises on alias without service" do
266
+ expect {
267
+ @srv.mkname( {:event=>'bob'} )
268
+ }.to raise_error %{Missing parts! {"event":"bob"}}
269
+ end
270
+
271
+ it "raises on alias without event" do
272
+ expect {
273
+ @srv.mkalias( {:service=>'bob'} )
274
+ }.to raise_error %{Missing parts! {"service":"bob"}}
275
+ end
276
+
277
+ it "raises on name without service" do
278
+ expect {
279
+ @srv.mkalias( {:event=>'bob'} )
280
+ }.to raise_error %{Missing parts! {"event":"bob"}}
281
+ end
282
+
283
+ it "raises on name without event" do
284
+ expect {
285
+ @srv.mkname( {:service=>'bob'} )
286
+ }.to raise_error %{Missing parts! {"service":"bob"}}
287
+ end
288
+ end
289
+
290
+ context "toRemoteItem" do
291
+ before(:example) do
292
+ allow(@srv).to receive(:warning)
293
+ end
294
+
295
+ it "reads one" do
296
+ Tempfile.open('foo') do |tio|
297
+ tio << %{--#EVENT device datapoint
298
+ -- do something.
299
+ Tsdb.write{tags={sn='1'},metrics={[data.alias]=data.value[2]}}
300
+ }.gsub(/^\s+/,'')
301
+ tio.close
302
+
303
+ ret = @srv.toRemoteItem(nil, tio.path)
304
+ expect(ret).to eq({:service=>'device',
305
+ :event=>'datapoint',
306
+ :line=>0,
307
+ :line_end=>3,
308
+ :local_path=>Pathname.new(tio.path),
309
+ :script=>%{--#EVENT device datapoint\n-- do something.\nTsdb.write{tags={sn='1'},metrics={[data.alias]=data.value[2]}}\n},
310
+ })
311
+ end
312
+ end
313
+
314
+ it "skips all when no header found" do
315
+ Tempfile.open('foo') do |tio|
316
+ tio << %{
317
+ -- do something.
318
+ Tsdb.write{tags={sn='1'},metrics={[data.alias]=data.value[2]}}
319
+ }.gsub(/^\s+/,'')
320
+ tio.close
321
+
322
+ ret = @srv.toRemoteItem(nil, tio.path)
323
+ expect(ret).to eq(nil)
324
+ end
325
+ end
326
+
327
+ it "skips junk at begining" do
328
+ Tempfile.open('foo') do |tio|
329
+ tio << %{
330
+ -- do something.
331
+ --#EVENT device datapoint
332
+ Tsdb.write{tags={sn='1'},metrics={[data.alias]=data.value[2]}}
333
+ }.gsub(/^\s+/,'')
334
+ tio.close
335
+
336
+ ret = @srv.toRemoteItem(nil, tio.path)
337
+ expect(ret).to eq({:service=>'device',
338
+ :event=>'datapoint',
339
+ :line=>1,
340
+ :line_end=>3,
341
+ :local_path=>Pathname.new(tio.path),
342
+ :script=>%{--#EVENT device datapoint\nTsdb.write{tags={sn='1'},metrics={[data.alias]=data.value[2]}}\n},
343
+ })
344
+ end
345
+ end
346
+
347
+ end
348
+
349
+ context "Matching" do
350
+ before(:example) do
351
+ @an_item = {
352
+ :service=>'bob',
353
+ :event=>'built',
354
+ :local_path=>Pathname.new('a/relative/path.lua'),
355
+ }
356
+ end
357
+ context "service" do
358
+ it "any event" do
359
+ ret = @srv.match(@an_item, '#bob#')
360
+ expect(ret).to be true
361
+ ret = @srv.match(@an_item, '#email#')
362
+ expect(ret).to be false
363
+ end
364
+ it "exact event" do
365
+ ret = @srv.match(@an_item, '#bob#built')
366
+ expect(ret).to be true
367
+ ret = @srv.match(@an_item, '#email#built')
368
+ expect(ret).to be false
369
+ end
370
+ end
371
+ context "any service" do
372
+ it "any event" do
373
+ ret = @srv.match(@an_item, '##')
374
+ expect(ret).to be true
375
+ end
376
+ it "exact event" do
377
+ ret = @srv.match(@an_item, '##built')
378
+ expect(ret).to be true
379
+ ret = @srv.match(@an_item, '##sent')
380
+ expect(ret).to be false
381
+ end
382
+ end
383
+ end
384
+ end
385
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,465 @@
1
+ require 'MrMurano/version'
2
+ require 'MrMurano/Solution-Services'
3
+ require 'tempfile'
4
+ require '_workspace'
5
+
6
+ RSpec.describe MrMurano::Library do
7
+ include_context "WORKSPACE"
8
+ before(:example) do
9
+ $cfg = MrMurano::Config.new
10
+ $cfg.load
11
+ $project = MrMurano::ProjectFile.new
12
+ $project.load
13
+ $cfg['net.host'] = 'bizapi.hosted.exosite.io'
14
+ $cfg['solution.id'] = 'XYZ'
15
+
16
+ @srv = MrMurano::Library.new
17
+ allow(@srv).to receive(:token).and_return("TTTTTTTTTT")
18
+ end
19
+
20
+ it "initializes" do
21
+ uri = @srv.endPoint('/')
22
+ expect(uri.to_s).to eq("https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/")
23
+ end
24
+
25
+ it "lists" do
26
+ body = {:items=>[{:id=>"9K0",
27
+ :name=>"debug",
28
+ :alias=>"XYZ_debug",
29
+ :solution_id=>"XYZ",
30
+ :created_at=>"2016-07-07T19:16:19.479Z",
31
+ :updated_at=>"2016-09-12T13:26:55.868Z"}],
32
+ :total=>1}
33
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library").
34
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
35
+ 'Content-Type'=>'application/json'}).
36
+ to_return(body: body.to_json)
37
+
38
+ ret = @srv.list()
39
+ expect(ret).to eq(body[:items])
40
+ end
41
+
42
+ context "fetching" do
43
+ it "fetches" do
44
+ body = {:id=>"9K0",
45
+ :name=>"debug",
46
+ :alias=>"XYZ_debug",
47
+ :solution_id=>"XYZ",
48
+ :created_at=>"2016-07-07T19:16:19.479Z",
49
+ :updated_at=>"2016-09-12T13:26:55.868Z",
50
+ :script=>%{-- lua code is here
51
+ function foo(bar)
52
+ return bar + 1
53
+ end
54
+ }
55
+ }
56
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/9K0").
57
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
58
+ 'Content-Type'=>'application/json'}).
59
+ to_return(body: body.to_json)
60
+
61
+ ret = @srv.fetch('9K0')
62
+ expect(ret).to eq(body[:script])
63
+ end
64
+
65
+ it "fetches with block" do
66
+ body = {:id=>"9K0",
67
+ :name=>"debug",
68
+ :alias=>"XYZ_debug",
69
+ :solution_id=>"XYZ",
70
+ :created_at=>"2016-07-07T19:16:19.479Z",
71
+ :updated_at=>"2016-09-12T13:26:55.868Z",
72
+ :script=>%{-- lua code is here
73
+ function foo(bar)
74
+ return bar + 1
75
+ end
76
+ }
77
+ }
78
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/9K0").
79
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
80
+ 'Content-Type'=>'application/json'}).
81
+ to_return(body: body.to_json)
82
+
83
+ ret = nil
84
+ @srv.fetch('9K0') {|sc| ret = sc}
85
+ expect(ret).to eq(body[:script])
86
+ end
87
+
88
+ it "Returns empty if script missing" do
89
+ body = {:id=>"9K0",
90
+ :name=>"debug",
91
+ :alias=>"XYZ_debug",
92
+ :solution_id=>"XYZ",
93
+ :created_at=>"2016-07-07T19:16:19.479Z",
94
+ :updated_at=>"2016-09-12T13:26:55.868Z",
95
+ }
96
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/9K0").
97
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
98
+ 'Content-Type'=>'application/json'}).
99
+ to_return(body: body.to_json)
100
+
101
+ ret = @srv.fetch('9K0')
102
+ expect(ret).to eq('')
103
+ end
104
+
105
+ it "Displays error if wrong result type" do
106
+ stub_request(:get, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/9K0").
107
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
108
+ 'Content-Type'=>'application/json'}).
109
+ to_return(body: "this isn't what we expected")
110
+
111
+ saved = $stderr
112
+ $stderr = StringIO.new
113
+ ret = @srv.fetch('9K0')
114
+ expect(ret).to eq('')
115
+ expect($stderr.string).to eq(%{\e[31mUnexpected result type, assuming empty instead: this isn't what we expected\e[0m\n})
116
+ $stderr = saved
117
+ end
118
+ end
119
+
120
+ it "removes" do
121
+ stub_request(:delete, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/9K0").
122
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
123
+ 'Content-Type'=>'application/json'}).
124
+ to_return(body: "")
125
+
126
+ ret = @srv.remove('9K0')
127
+ expect(ret).to eq({})
128
+ end
129
+
130
+ context "uploads" do
131
+ it "over old version" do
132
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
133
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
134
+ 'Content-Type'=>'application/json'}).
135
+ to_return(body: "")
136
+
137
+ Tempfile.open('foo') do |tio|
138
+ tio << %{-- lua code is here
139
+ function foo(bar)
140
+ return bar + 1
141
+ end
142
+ }
143
+ tio.close
144
+
145
+ ret = @srv.upload(tio.path, {:id=>"9K0",
146
+ :name=>"debug",
147
+ :alias=>"XYZ_debug",
148
+ :solution_id=>"XYZ",
149
+ })
150
+ expect(ret)
151
+ end
152
+ end
153
+
154
+ it "when nothing is there" do
155
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
156
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
157
+ 'Content-Type'=>'application/json'}).
158
+ to_return(status: 404)
159
+ stub_request(:post, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/").
160
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
161
+ 'Content-Type'=>'application/json'}).
162
+ to_return(body: "")
163
+
164
+ Tempfile.open('foo') do |tio|
165
+ tio << %{-- lua code is here
166
+ function foo(bar)
167
+ return bar + 1
168
+ end
169
+ }
170
+ tio.close
171
+
172
+ ret = @srv.upload(tio.path, {:id=>"9K0",
173
+ :name=>"debug",
174
+ :alias=>"XYZ_debug",
175
+ :solution_id=>"XYZ",
176
+ })
177
+ expect(ret)
178
+ end
179
+ end
180
+
181
+ it "shows other errors" do
182
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
183
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
184
+ 'Content-Type'=>'application/json'}).
185
+ to_return(status: 418, body: %{{"teapot":true}})
186
+
187
+ Tempfile.open('foo') do |tio|
188
+ tio << %{-- lua code is here
189
+ function foo(bar)
190
+ return bar + 1
191
+ end
192
+ }
193
+ tio.close
194
+
195
+ expect(@srv).to receive(:error).and_return(nil)
196
+ ret = @srv.upload(tio.path, {:id=>"9K0",
197
+ :name=>"debug",
198
+ :alias=>"XYZ_debug",
199
+ :solution_id=>"XYZ",
200
+ })
201
+ expect(ret)
202
+ end
203
+ end
204
+
205
+ it "over old version; replacing cache miss" do
206
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
207
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
208
+ 'Content-Type'=>'application/json'}).
209
+ to_return(body: "")
210
+
211
+ Tempfile.open('foo') do |tio|
212
+ tio << %{-- lua code is here
213
+ function foo(bar)
214
+ return bar + 1
215
+ end
216
+ }
217
+ tio.close
218
+
219
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
220
+ FileUtils.touch(cacheFile.to_path)
221
+ ret = @srv.upload(tio.path, {:id=>"9K0",
222
+ :name=>"debug",
223
+ :alias=>"XYZ_debug",
224
+ :solution_id=>"XYZ",
225
+ })
226
+ expect(ret)
227
+ end
228
+ end
229
+
230
+ it "over old version; replacing cache hit" do
231
+ stub_request(:put, "https://bizapi.hosted.exosite.io/api:1/solution/XYZ/library/XYZ_debug").
232
+ with(:headers=>{'Authorization'=>'token TTTTTTTTTT',
233
+ 'Content-Type'=>'application/json'}).
234
+ to_return(body: "")
235
+
236
+ Tempfile.open('foo') do |tio|
237
+ tio << %{-- lua code is here
238
+ function foo(bar)
239
+ return bar + 1
240
+ end
241
+ }
242
+ tio.close
243
+
244
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
245
+ cacheFile.open('w') do |cfio|
246
+ cfio << {tio.path=>{:sha1=>"6",
247
+ :updated_at=>Time.now.getutc.to_datetime.iso8601(3)}
248
+ }.to_yaml
249
+ end
250
+ ret = @srv.upload(tio.path, {:id=>"9K0",
251
+ :name=>"debug",
252
+ :alias=>"XYZ_debug",
253
+ :solution_id=>"XYZ",
254
+ })
255
+ expect(ret)
256
+ end
257
+ end
258
+ end
259
+
260
+ context "compares" do
261
+ before(:example) do
262
+ @iA = {:id=>"9K0",
263
+ :name=>"debug",
264
+ :alias=>"XYZ_debug",
265
+ :solution_id=>"XYZ",
266
+ :created_at=>"2016-07-07T19:16:19.479Z",
267
+ :updated_at=>"2016-09-12T13:26:55.868Z"}
268
+ @iB = {:id=>"9K0",
269
+ :name=>"debug",
270
+ :alias=>"XYZ_debug",
271
+ :solution_id=>"XYZ",
272
+ :created_at=>"2016-07-07T19:16:19.479Z",
273
+ :updated_at=>"2016-09-12T13:26:55.868Z"}
274
+ end
275
+ it "both have updated_at" do
276
+ ret = @srv.docmp(@iA, @iB)
277
+ expect(ret).to eq(false)
278
+ end
279
+
280
+ context "iA is a local file" do
281
+ it "no cacheFile" do
282
+ Tempfile.open('foo') do |tio|
283
+ tio << "something"
284
+ tio.close
285
+ iA = @iA.reject{|k,v| k == :updated_at}.merge({
286
+ :local_path => Pathname.new(tio.path)
287
+ })
288
+ ret = @srv.docmp(iA, @iB)
289
+ expect(ret).to eq(true)
290
+
291
+ iB = @iB.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
292
+ ret = @srv.docmp(iA, iB)
293
+ expect(ret).to eq(false)
294
+ end
295
+ end
296
+
297
+ it "cache miss" do
298
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
299
+ FileUtils.touch(cacheFile.to_path)
300
+ Tempfile.open('foo') do |tio|
301
+ tio << "something"
302
+ tio.close
303
+ iA = @iA.reject{|k,v| k == :updated_at}.merge({
304
+ :local_path => Pathname.new(tio.path)
305
+ })
306
+ ret = @srv.docmp(iA, @iB)
307
+ expect(ret).to eq(true)
308
+
309
+ iB = @iB.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
310
+ ret = @srv.docmp(iA, iB)
311
+ expect(ret).to eq(false)
312
+ end
313
+ end
314
+
315
+ it "cache hit" do
316
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
317
+ Tempfile.open('foo') do |tio|
318
+ tio << "something"
319
+ tio.close
320
+ tio_mtime = Pathname.new(tio.path).mtime.getutc
321
+ entry = {
322
+ :sha1=>Digest::SHA1.file(tio.path).hexdigest,
323
+ :updated_at=>tio_mtime.to_datetime.iso8601(3)
324
+ }
325
+ cacheFile.open('w') do |io|
326
+ cache = {}
327
+ cache[tio.path] = entry
328
+ io << cache.to_yaml
329
+ end
330
+
331
+ iA = @iA.reject{|k,v| k == :updated_at}.merge({
332
+ :local_path => Pathname.new(tio.path)
333
+ })
334
+ ret = @srv.docmp(iA, @iB)
335
+ expect(ret).to eq(true)
336
+
337
+ iB = @iB.merge({:updated_at=>tio_mtime})
338
+ ret = @srv.docmp(iA, iB)
339
+ expect(ret).to eq(false)
340
+ end
341
+ end
342
+ end
343
+
344
+ context "iB is a local file" do
345
+ it "no cacheFile" do
346
+ Tempfile.open('foo') do |tio|
347
+ tio << "something"
348
+ tio.close
349
+ iB = @iB.reject{|k,v| k == :updated_at}.merge({
350
+ :local_path => Pathname.new(tio.path)
351
+ })
352
+ ret = @srv.docmp(@iA, iB)
353
+ expect(ret).to eq(true)
354
+
355
+ iA = @iA.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
356
+ ret = @srv.docmp(iA, iB)
357
+ expect(ret).to eq(false)
358
+ end
359
+ end
360
+
361
+ it "cache miss" do
362
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
363
+ FileUtils.touch(cacheFile.to_path)
364
+ Tempfile.open('foo') do |tio|
365
+ tio << "something"
366
+ tio.close
367
+ iB = @iB.reject{|k,v| k == :updated_at}.merge({
368
+ :local_path => Pathname.new(tio.path)
369
+ })
370
+ ret = @srv.docmp(@iA, iB)
371
+ expect(ret).to eq(true)
372
+
373
+ iA = @iA.merge({:updated_at=>Pathname.new(tio.path).mtime.getutc})
374
+ ret = @srv.docmp(iA, iB)
375
+ expect(ret).to eq(false)
376
+ end
377
+ end
378
+
379
+ it "cache hit" do
380
+ cacheFile = $cfg.file_at(@srv.cacheFileName)
381
+ Tempfile.open('foo') do |tio|
382
+ tio << "something"
383
+ tio.close
384
+ tio_mtime = Pathname.new(tio.path).mtime.getutc
385
+ entry = {
386
+ :sha1=>Digest::SHA1.file(tio.path).hexdigest,
387
+ :updated_at=>tio_mtime.to_datetime.iso8601(3)
388
+ }
389
+ cacheFile.open('w') do |io|
390
+ cache = {}
391
+ cache[tio.path] = entry
392
+ io << cache.to_yaml
393
+ end
394
+
395
+ iB = @iB.reject{|k,v| k == :updated_at}.merge({
396
+ :local_path => Pathname.new(tio.path)
397
+ })
398
+ ret = @srv.docmp(@iA, iB)
399
+ expect(ret).to eq(true)
400
+
401
+ iA = @iA.merge({:updated_at=>tio_mtime})
402
+ ret = @srv.docmp(iA, iB)
403
+ expect(ret).to eq(false)
404
+ end
405
+ end
406
+ end
407
+ end
408
+
409
+ context "Lookup functions" do
410
+ it "gets local name" do
411
+ ret = @srv.tolocalname({ :name=>"bob" }, nil)
412
+ expect(ret).to eq('bob.lua')
413
+ end
414
+
415
+ it "gets synckey" do
416
+ ret = @srv.synckey({ :name=>'device' })
417
+ expect(ret).to eq("device")
418
+ end
419
+
420
+ it "gets searchfor" do
421
+ $cfg['modules.searchFor'] = %{a b c/**/d/*.bob}
422
+ ret = @srv.searchFor
423
+ expect(ret).to eq(["a", "b", "c/**/d/*.bob"])
424
+ end
425
+
426
+ it "gets ignoring" do
427
+ $cfg['modules.ignoring'] = %{a b c/**/d/*.bob}
428
+ ret = @srv.ignoring
429
+ expect(ret).to eq(["a", "b", "c/**/d/*.bob"])
430
+ end
431
+
432
+ it "raises on alias without service" do
433
+ expect {
434
+ @srv.mkname( {:event=>'bob'} )
435
+ }.to raise_error %{Missing parts! {"event":"bob"}}
436
+ end
437
+
438
+ it "raises on alias without event" do
439
+ expect {
440
+ @srv.mkalias( {:service=>'bob'} )
441
+ }.to raise_error %{Missing parts! {"service":"bob"}}
442
+ end
443
+
444
+ it "raises on name without service" do
445
+ expect {
446
+ @srv.mkalias( {:event=>'bob'} )
447
+ }.to raise_error %{Missing parts! {"event":"bob"}}
448
+ end
449
+
450
+ it "raises on name without event" do
451
+ expect {
452
+ @srv.mkname( {:service=>'bob'} )
453
+ }.to raise_error %{Missing parts! {"service":"bob"}}
454
+ end
455
+ end
456
+
457
+ context "toRemoteItem" do
458
+ it "reads one" do
459
+ path = Pathname.new(@projectDir) + 'test.lua'
460
+ ret = @srv.toRemoteItem(nil, path)
461
+ expect(ret).to eq({:name=>'test'})
462
+ end
463
+ end
464
+ end
465
+ # vim: set ai et sw=2 ts=2 :