toq 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fa9dccb95205fadf37ce8a48a133f6e08f5c1f5d07f2377041562c3a08e39b3
4
- data.tar.gz: d0ed2e661f09eda4815eed365c3397fa920192e8c42e8cc55109733d66229c71
3
+ metadata.gz: c4a52cfe51fc062860cb41237c2453b35ccc2b7c7447491a8fb0e3bb5578c26c
4
+ data.tar.gz: 58c73eef95e49b2cd66ab977b3d6fc70a3705f0a79000c0c2db05bc50804618f
5
5
  SHA512:
6
- metadata.gz: 795adb9468a8b873b8c9f8fe41726368eb2314abf531f8d011d6606fbe519b011ccf0ceb10e5a52682b6ed4dee6b7abd14acd6b913357a5e6f31c81c201d8ac1
7
- data.tar.gz: 26a6fbf1afa05c8cc0d8702bdc0e40a0597ff26c235c71ca0e079b33f0686f99990d2a102927281690f49c506503d114f8306d30a6621257245f55e5acf9801c
6
+ metadata.gz: e74a30760feac7886f77c025f975df9fd9d4cb0aa36d8f3105f74b1fbbc43508b259db5a2f6d443f268b88174b6cdc9f17149766f88ed3b47408b9363a099d79
7
+ data.tar.gz: d9cde530727fdb95148c404a0d02884c46278f2537d88c55e99e1c0393a056b892ae9d9aa01bfaa9acfb47f23a28a4cca6dd67a8a9e627cb150cb276d3614ae7
data/CHANGELOG.md CHANGED
@@ -1,5 +1 @@
1
1
  # ChangeLog
2
-
3
- # 0.0.3
4
-
5
- - Don't whitelist public methods, they could have changed dynamically after server start.
data/README.md CHANGED
@@ -3,12 +3,12 @@
3
3
  <table>
4
4
  <tr>
5
5
  <th>Version</th>
6
- <td>0.0.1</td>
6
+ <td>0.0.4</td>
7
7
  </tr>
8
8
  <tr>
9
9
  <th>Github page</th>
10
10
  <td><a href="http://github.com/qadron/toq">http://github.com/qadron/toq</a></td>
11
- <tr/>
11
+ </tr>
12
12
  <tr>
13
13
  <th>Code Documentation</th>
14
14
  <td><a href="http://rubydoc.info/github/qadron/toq/">http://rubydoc.info/github/qadron/toq/</a></td>
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC EM
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq EM
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
data/lib/toq/client.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC EM
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq EM
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
@@ -22,6 +22,8 @@ class Client
22
22
  # Default amount of connections to maintain in the re-use pool.
23
23
  DEFAULT_CONNECTION_POOL_SIZE = 1
24
24
 
25
+ attr_reader :reactor
26
+
25
27
  # @return [Hash]
26
28
  # Options hash.
27
29
  attr_reader :opts
@@ -87,7 +89,11 @@ class Client
87
89
 
88
90
  @pool_size = @opts[:connection_pool_size] || DEFAULT_CONNECTION_POOL_SIZE
89
91
 
90
- @reactor = Raktr.global
92
+ @reactor = Raktr.new
93
+
94
+ @reactor.on_error do |e|
95
+ p e
96
+ end
91
97
 
92
98
  @connections = @reactor.create_queue
93
99
  @connection_count = 0
@@ -200,7 +206,13 @@ class Client
200
206
  def set_exception( req, e )
201
207
  msg = @socket ? " for '#{@socket}'." : " for '#{@host}:#{@port}'."
202
208
 
203
- exc = Exceptions::ConnectionError.new( e.to_s + msg )
209
+ exc = case e
210
+ when Errno::ENOENT, Errno::EACCES
211
+ Exceptions::ConnectionError.new( e.to_s + msg )
212
+
213
+ else
214
+ Exception.new( e.to_s + msg )
215
+ end
204
216
 
205
217
  exc.set_backtrace e.backtrace
206
218
  req.callback.call exc
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
data/lib/toq/message.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
data/lib/toq/protocol.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC EM
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq EM
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
data/lib/toq/proxy.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
data/lib/toq/request.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
data/lib/toq/response.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC EM project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC EM
3
+ This file is part of the Toq EM project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq EM
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
data/lib/toq/server.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC EM project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC EM
3
+ This file is part of the Toq EM project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq EM
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
@@ -29,6 +29,8 @@ class Server
29
29
  # @return [Logger]
30
30
  attr_reader :logger
31
31
 
32
+ attr_reader :reactor
33
+
32
34
  # Starts the RPC server.
33
35
  #
34
36
  # @example Example options:
@@ -98,6 +100,10 @@ class Server
98
100
 
99
101
  @reactor = Raktr.global
100
102
 
103
+ @reactor.on_error do |e|
104
+ @logger.error( 'System' ){ "#{e}" }
105
+ end
106
+
101
107
  clear_handlers
102
108
  end
103
109
 
@@ -128,13 +134,7 @@ class Server
128
134
  # @param [Object] obj
129
135
  # Instantiated server object to expose.
130
136
  def add_handler( name, obj )
131
- @objects[name] = obj
132
- @methods[name] = Set.new
133
- @async_methods[name] = Set.new
134
-
135
- obj.class.public_instance_methods( false ).each do |method|
136
- @async_methods[name] << method.to_s if async_check( obj.method( method ) )
137
- end
137
+ @objects[name] = obj
138
138
  end
139
139
 
140
140
  # Clears all handlers and their associated information like methods and
@@ -144,20 +144,23 @@ class Server
144
144
  # @see #add_async_check
145
145
  def clear_handlers
146
146
  @objects = {}
147
- @methods = {}
148
-
149
- @async_checks = []
150
- @async_methods = {}
147
+ @async_checks = []
151
148
  end
152
149
 
153
150
  # Runs the server and blocks while `Raktr` is running.
154
151
  def run
155
- @reactor.run { start }
152
+ @reactor.run do
153
+ @reactor.on_error do |e|
154
+ @logger.error( 'System' ){ "#{e}" }
155
+ end
156
+
157
+ start
158
+ end
156
159
  end
157
160
 
158
161
  # Starts the server but does not block.
159
162
  def start
160
- @logger.info( 'System' ){ 'RPC Server started.' }
163
+ @logger.info( 'System' ){ "[PID #{Process.pid}] RPC Server started." }
161
164
  @logger.info( 'System' ) do
162
165
  interface = @socket ? @socket : "#{@host}:#{@port}"
163
166
  "Listening on #{interface}"
@@ -228,7 +231,7 @@ class Server
228
231
  private
229
232
 
230
233
  def async?( objname, method )
231
- @async_methods[objname].include?( method )
234
+ async_check( @objects[objname].method( method ) )
232
235
  end
233
236
 
234
237
  def async_check( method )
@@ -257,7 +260,7 @@ class Server
257
260
  end
258
261
 
259
262
  def object_exist?( obj_name )
260
- @objects[obj_name] ? true : false
263
+ !!@objects[obj_name]
261
264
  end
262
265
 
263
266
  end
data/lib/toq/version.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
8
8
 
9
9
  module Toq
10
10
 
11
- VERSION = '0.0.3'
11
+ VERSION = '0.0.4'
12
12
 
13
13
  end
data/lib/toq.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
 
3
- This file is part of the Arachni-RPC project and may be subject to
4
- redistribution and commercial restrictions. Please see the Arachni-RPC
3
+ This file is part of the Toq project and may be subject to
4
+ redistribution and commercial restrictions. Please see the Toq
5
5
  web site for more information on licensing and terms of use.
6
6
 
7
7
  =end
@@ -19,7 +19,7 @@ def rpc_opts_with_socket
19
19
  opts.delete( :host )
20
20
  opts.delete( :port )
21
21
 
22
- opts.merge( socket: '/tmp/arachni-rpc-test' )
22
+ opts.merge( socket: '/tmp/toq-rpc-test' )
23
23
  end
24
24
 
25
25
  def rpc_opts_with_ssl_primitives
@@ -53,12 +53,8 @@ end
53
53
 
54
54
  class Test < Parent
55
55
 
56
- # In order to make inherited methods accessible you've got to explicitly
57
- # make them public.
58
- private :foo
59
- public :foo
60
-
61
56
  def delay( arg, &block )
57
+ Raktr.global.run_in_thread if !Raktr.global.running?
62
58
  Raktr.global.delay( 1 ) { block.call( arg ) }
63
59
  end
64
60
 
@@ -1,7 +1,7 @@
1
1
  require_relative 'server'
2
2
 
3
3
  opts = rpc_opts.merge(
4
- socket: '/tmp/arachni-rpc-test',
4
+ socket: '/tmp/toq-rpc-test',
5
5
  serializer: Marshal
6
6
  )
7
7
 
data/spec/spec_helper.rb CHANGED
@@ -21,8 +21,10 @@ RSpec.configure do |config|
21
21
  config.color = true
22
22
  config.add_formatter :documentation
23
23
 
24
+ # config.filter_run_including focus: true
25
+
24
26
  config.before( :suite ) do
25
- File.delete( '/tmp/arachni-rpc-test' ) rescue nil
27
+ File.delete( '/tmp/toq-rpc-test' ) rescue nil
26
28
 
27
29
  files = %w(basic with_ssl_primitives)
28
30
  files << 'unix_socket' if Raktr.supports_unix_sockets?
@@ -30,7 +32,7 @@ RSpec.configure do |config|
30
32
  files.each do |name|
31
33
  server_pids << quiet_spawn( name ).tap { |pid| Process.detach( pid ) }
32
34
  end
33
- sleep 5
35
+ sleep 1
34
36
  end
35
37
 
36
38
  config.after( :suite ) do
@@ -3,13 +3,11 @@ require 'spec_helper'
3
3
  describe Toq::Client do
4
4
 
5
5
  def wait
6
- Raktr.global.wait rescue Raktr::Error::NotRunning
6
+ reactor.wait rescue reactor::Error::NotRunning
7
7
  end
8
8
 
9
9
  before(:each) do
10
- if Raktr.global.running?
11
- Raktr.stop
12
- end
10
+ reactor.stop if reactor.running?
13
11
  end
14
12
 
15
13
  let(:arguments) do
@@ -20,7 +18,7 @@ describe Toq::Client do
20
18
  [ 4 ]
21
19
  ]
22
20
  end
23
- let(:reactor) { Raktr.global }
21
+ let(:reactor) { subject.reactor }
24
22
  let(:handler) { 'test' }
25
23
  let(:remote_method) { 'foo' }
26
24
  let(:options) { rpc_opts }
@@ -69,7 +67,7 @@ describe Toq::Client do
69
67
  subject.call( "#{handler}.#{remote_method}", arg ) do |res|
70
68
  cnt += 1
71
69
  mismatches << [i, arg, res] if arg != res
72
- Raktr.stop if cnt == n || mismatches.any?
70
+ reactor.stop if cnt == n || mismatches.any?
73
71
  end
74
72
  end
75
73
  wait
@@ -86,7 +84,7 @@ describe Toq::Client do
86
84
  response = nil
87
85
  call do |res|
88
86
  response = res
89
- Raktr.stop
87
+ reactor.stop
90
88
  end
91
89
  wait
92
90
 
@@ -167,7 +165,7 @@ describe Toq::Client do
167
165
  subject.call( "#{handler}.#{remote_method}", arg ) do |res|
168
166
  cnt += 1
169
167
  mismatches << [i, arg, res] if arg != res
170
- Raktr.stop if cnt == n || mismatches.any?
168
+ reactor.stop if cnt == n || mismatches.any?
171
169
  end
172
170
  end
173
171
 
@@ -187,7 +185,7 @@ describe Toq::Client do
187
185
  response = nil
188
186
  call do |res|
189
187
  response = res
190
- Raktr.stop
188
+ reactor.stop
191
189
  end
192
190
  wait
193
191
 
@@ -199,11 +197,10 @@ describe Toq::Client do
199
197
  it 'should be able to perform asynchronous calls' do
200
198
  response = nil
201
199
 
202
- Raktr.stop
203
200
  reactor.run do
204
201
  call do |res|
205
202
  response = res
206
- Raktr.stop
203
+ reactor.stop
207
204
  end
208
205
  end
209
206
 
@@ -213,13 +210,12 @@ describe Toq::Client do
213
210
  it 'should not be able to perform synchronous calls' do
214
211
  exception = nil
215
212
 
216
- Raktr.stop
217
213
  reactor.run do
218
214
  begin
219
215
  call
220
216
  rescue => e
221
217
  exception = e
222
- Raktr.stop
218
+ reactor.stop
223
219
  end
224
220
  end
225
221
 
@@ -235,7 +231,7 @@ describe Toq::Client do
235
231
  response = nil
236
232
  call do |res|
237
233
  response = res
238
- Raktr.stop
234
+ reactor.stop
239
235
  end
240
236
  wait
241
237
 
@@ -252,7 +248,7 @@ describe Toq::Client do
252
248
 
253
249
  call do |res|
254
250
  response = res
255
- Raktr.stop
251
+ reactor.stop
256
252
  end
257
253
  wait
258
254
 
@@ -261,6 +257,23 @@ describe Toq::Client do
261
257
  end
262
258
  end
263
259
 
260
+ # context 'and requesting a non-public method' do
261
+ # let(:remote_method) { 'bar' }
262
+ #
263
+ # it "returns #{Toq::Exceptions::InvalidMethod}" do
264
+ # response = nil
265
+ #
266
+ # call do |res|
267
+ # response = res
268
+ # reactor.stop
269
+ # end
270
+ # wait
271
+ #
272
+ # response.should be_rpc_invalid_method_error
273
+ # response.should be_kind_of Toq::Exceptions::InvalidMethod
274
+ # end
275
+ # end
276
+
264
277
  context 'and there is a remote exception' do
265
278
  let(:remote_method) { :exception }
266
279
 
@@ -268,7 +281,7 @@ describe Toq::Client do
268
281
  response = nil
269
282
  call do |res|
270
283
  response = res
271
- Raktr.stop
284
+ reactor.stop
272
285
  end
273
286
  wait
274
287
 
@@ -305,6 +318,19 @@ describe Toq::Client do
305
318
  end
306
319
  end
307
320
 
321
+ # context 'and requesting a non-public method' do
322
+ # let(:remote_method) { 'bar' }
323
+ #
324
+ # it "raises #{Toq::Exceptions::InvalidMethod}" do
325
+ # begin
326
+ # call
327
+ # rescue => e
328
+ # e.rpc_invalid_method_error?.should be_true
329
+ # e.should be_kind_of Toq::Exceptions::InvalidMethod
330
+ # end
331
+ # end
332
+ # end
333
+
308
334
  context 'and there is a remote exception' do
309
335
  let(:remote_method) { :exception }
310
336
 
@@ -333,11 +359,10 @@ describe Toq::Client do
333
359
  it 'should not be able to establish a connection' do
334
360
  response = nil
335
361
 
336
- Raktr.stop
337
362
  reactor.run do
338
363
  call do |res|
339
364
  response = res
340
- Raktr.stop
365
+ reactor.stop
341
366
  end
342
367
  end
343
368
 
@@ -351,11 +376,10 @@ describe Toq::Client do
351
376
  it 'should not be able to establish a connection' do
352
377
  response = nil
353
378
 
354
- Raktr.stop
355
379
  reactor.run do
356
380
  call do |res|
357
381
  response = res
358
- Raktr.stop
382
+ reactor.stop
359
383
  end
360
384
  end
361
385
 
@@ -50,17 +50,17 @@ describe Toq::Exceptions do
50
50
  end
51
51
  end
52
52
 
53
- describe '#rpc_invalid_method_error?' do
54
- context 'for invalid method RPC exceptions' do
55
- subject { described_class::InvalidMethod.new.rpc_invalid_method_error? }
56
- it { should be_true }
57
- end
58
-
59
- context 'for other exceptions' do
60
- subject { ::Exception.new.rpc_invalid_method_error? }
61
- it { should be_false }
62
- end
63
- end
53
+ # describe '#rpc_invalid_method_error?' do
54
+ # context 'for invalid method RPC exceptions' do
55
+ # subject { described_class::InvalidMethod.new.rpc_invalid_method_error? }
56
+ # it { should be_true }
57
+ # end
58
+ #
59
+ # context 'for other exceptions' do
60
+ # subject { ::Exception.new.rpc_invalid_method_error? }
61
+ # it { should be_false }
62
+ # end
63
+ # end
64
64
 
65
65
  describe '#rpc_invalid_token_error?' do
66
66
  context 'for RPC exceptions' do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Toq::Server
4
- public :async?, :async_check, :object_exist?, :public_method?
4
+ public :async?, :async_check, :object_exist?
5
5
  attr_accessor :proxy
6
6
  end
7
7
 
@@ -111,19 +111,4 @@ describe Toq::Server do
111
111
  end
112
112
  end
113
113
 
114
- describe '#public_method?' do
115
- context 'when a method is public' do
116
- it 'returns true' do
117
- subject.public_method?( 'test', 'foo' ).should be_true
118
- end
119
- end
120
-
121
- context 'when a method is non-existent or not public' do
122
- it 'returns false' do
123
- subject.public_method?( 'test', 'bar' ).should be_false
124
- end
125
- end
126
- end
127
-
128
114
  end
129
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tasos Laskos
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-22 00:00:00.000000000 Z
11
+ date: 2023-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: raktr
@@ -90,27 +90,27 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
90
  - !ruby/object:Gem::Version
91
91
  version: '0'
92
92
  requirements: []
93
- rubygems_version: 3.3.7
93
+ rubygems_version: 3.4.9
94
94
  signing_key:
95
95
  specification_version: 4
96
96
  summary: Simple RPC protocol.
97
97
  test_files:
98
- - spec/pems/cacert.pem
99
- - spec/pems/client/cert.pem
100
- - spec/pems/client/foo-cert.pem
101
- - spec/pems/client/foo-key.pem
102
- - spec/pems/client/key.pem
103
- - spec/pems/server/cert.pem
104
- - spec/pems/server/key.pem
105
- - spec/servers/basic.rb
106
- - spec/servers/server.rb
107
- - spec/servers/unix_socket.rb
108
- - spec/servers/with_ssl_primitives.rb
109
98
  - spec/spec_helper.rb
110
- - spec/toq/client_spec.rb
111
- - spec/toq/exceptions_spec.rb
112
- - spec/toq/message_spec.rb
113
- - spec/toq/proxy_spec.rb
114
99
  - spec/toq/request_spec.rb
115
100
  - spec/toq/response_spec.rb
101
+ - spec/toq/client_spec.rb
102
+ - spec/toq/exceptions_spec.rb
116
103
  - spec/toq/server_spec.rb
104
+ - spec/toq/proxy_spec.rb
105
+ - spec/toq/message_spec.rb
106
+ - spec/servers/server.rb
107
+ - spec/servers/unix_socket.rb
108
+ - spec/servers/with_ssl_primitives.rb
109
+ - spec/servers/basic.rb
110
+ - spec/pems/cacert.pem
111
+ - spec/pems/server/cert.pem
112
+ - spec/pems/server/key.pem
113
+ - spec/pems/client/foo-key.pem
114
+ - spec/pems/client/foo-cert.pem
115
+ - spec/pems/client/cert.pem
116
+ - spec/pems/client/key.pem