xchan.rb 0.17.1 → 0.18.0

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: 5509107cf1cda5e847f3c15e19c81ba9323c2dbb524a7ef808eeb820d5bcdeb9
4
- data.tar.gz: 43deff543ee38ace3ca8a083a043eb1c6bbedec9143bd2c8e17de50f13127031
3
+ metadata.gz: 49c3ec314ad19f47d91dd30c854e94ad184fd70a0cb5ed7fd0139b506b295c6e
4
+ data.tar.gz: 1ba90eb765464330c3c6c35385c6ce6732f0bd95cd21e85be236576b7a0ba7c5
5
5
  SHA512:
6
- metadata.gz: d5455dd6c714bc4060ec1f563b46d8a9eaee32e5aa58c2a2508de99f53fc29e346d07ac04e719822bc394b66ac6ba6ddf5585bf7958c606a0f1f375c113b4310
7
- data.tar.gz: '09bd28506d18a63e8e917ad1189c708cc6643b852707508ee0edf563064bd3618d3ae251d85e06f618672c414537b4da3db0538b61e4c11c2a6c64fff3394f38'
6
+ metadata.gz: d29f66b50713d1277b25ad2900bbcd5a99ac1589a921e0b0a8ccd2028e534204ffc8a382b68f3ba48947aa2be8fda90843adda2fbdf133db3cf9fb230f2a5873
7
+ data.tar.gz: 218b603663b0cac0af9c6780e942c74decb096045e9a7eef14daf5c6644286bd2ee8e1969445260952425bfad08b4bd2fb588a6a1d1f3be0b45d0913337575b5
@@ -12,7 +12,7 @@ jobs:
12
12
  fail-fast: false
13
13
  matrix:
14
14
  os: [ubuntu-latest, macos-latest]
15
- ruby: [3.1, 3.2, 3.3]
15
+ ruby: [3.2, 3.3]
16
16
  runs-on: ${{ matrix.os }}
17
17
  steps:
18
18
  - uses: actions/checkout@v2
@@ -20,7 +20,7 @@ jobs:
20
20
  with:
21
21
  ruby-version: ${{ matrix.ruby }}
22
22
  - run: bundle install
23
- - run: SERIALIZER=marshal bundle exec rake
24
- - run: SERIALIZER=json bundle exec rake
25
- - run: SERIALIZER=yaml bundle exec rake
26
- - run: SERIALIZER=pure bundle exec rake
23
+ - run: SERIALIZER=marshal; for t in *_test.rb; do ruby test/${t}; done
24
+ - run: SERIALIZER=json; for t in *_test.rb; do ruby test/${t}; done
25
+ - run: SERIALIZER=yaml; for t in *_test.rb; do ruby test/${t}; done
26
+ - run: SERIALIZER=pure; for t in *_test.rb; do ruby test/${t}; done
data/.projectile CHANGED
@@ -1,4 +1,5 @@
1
- +.
1
+ +/
2
+ +/.github/
2
3
  -/doc/
3
4
  -/.yardoc/
4
5
  -/.gems/
data/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  xchan.rb is an easy to use library for InterProcess
4
4
  Communication (IPC). The library provides a channel
5
- that can transfer Ruby objects between Ruby processes
6
- with a parent <-> child relationship.
5
+ that can help facilitate communication between Ruby
6
+ processes who have a parent &lt;=&gt; child relationship.
7
7
 
8
8
  ## Examples
9
9
 
@@ -11,30 +11,25 @@ with a parent <-> child relationship.
11
11
 
12
12
  #### Options
13
13
 
14
- The first argument given to xchan is the serializer
15
- that it should use. A channel that will communicate
16
- in pure strings (ie with no serialization) is
17
- available as `xchan(:pure)`.
18
-
19
- Otherwise, when a channel is written to or read from,
20
- a Ruby object is serialized (on write) or deserialized
21
- (on read). The serializers available to choose from
22
- are `xchan(:marshal)`, `xchan(:json)`, and `xchan(:yaml)`.
23
- The example uses
24
- [`Marshal`](https://www.rubydoc.info/stdlib/core/Marshal):
14
+ The first argument provided to xchan is the serializer
15
+ that should be used. A channel that will communicate
16
+ purely in strings (in other words: without serialization)
17
+ is available as `xchan(:pure)` - otherwise a wide range of
18
+ serializers are available by default: `xchan(:marshal)`,
19
+ `xchan(:json)`, and `xchan(:yaml)`.
25
20
 
26
21
  ```ruby
27
22
  require "xchan"
28
23
 
29
24
  ##
30
- # This channel uses Marshal to serialize objects
25
+ # Marshal as the serializer
31
26
  ch = xchan(:marshal)
32
27
  Process.wait fork { ch.send(5) }
33
- print "There are ", ch.recv + 7, " disciples and the same number of tribes", "\n"
28
+ print "#{ch.recv} + 7 = 12", "\n"
34
29
  ch.close
35
30
 
36
31
  ##
37
- # There are 12 disciples and the same number of tribes
32
+ # 5 + 7 = 12
38
33
  ```
39
34
 
40
35
  ### Read operations
@@ -52,13 +47,14 @@ the parent process writes to the channel:
52
47
  require "xchan"
53
48
 
54
49
  ch = xchan(:marshal)
55
- Process.detach fork {
50
+ fork do
56
51
  print "Received a random number (child process): ", ch.recv, "\n"
57
- }
52
+ end
58
53
  sleep(1)
59
54
  print "Send a random number (from parent process)", "\n"
60
55
  ch.send(rand(21))
61
56
  ch.close
57
+ Process.wait
62
58
 
63
59
  ##
64
60
  # Send a random number (from parent process)
@@ -183,7 +179,7 @@ print "The maximum size of a single message is: ", sndbuf.int, " bytes.\n"
183
179
  ## Documentation
184
180
 
185
181
  A complete API reference is available at
186
- [0x1eef.github.io/x/xchan.rb](https://0x1eef.github.io/x/xchan.rb/).
182
+ [0x1eef.github.io/x/xchan.rb](https://0x1eef.github.io/x/xchan.rb/)
187
183
 
188
184
  ## Install
189
185
 
@@ -193,11 +189,11 @@ xchan.rb can be installed via rubygems.org:
193
189
 
194
190
  ## Sources
195
191
 
196
- * [Source code (GitHub)](https://github.com/0x1eef/xchan.rb#readme)
197
- * [Source code (GitLab)](https://gitlab.com/0x1eef/xchan.rb#about)
192
+ * [GitHub](https://github.com/0x1eef/xchan.rb#readme)
193
+ * [GitLab](https://gitlab.com/0x1eef/xchan.rb#about)
198
194
 
199
- ## <a id="license"> License </a>
195
+ ## License
200
196
 
201
- [BSD Zero Clause](https://choosealicense.com/licenses/0bsd/).
197
+ [BSD Zero Clause](https://choosealicense.com/licenses/0bsd/)
202
198
  <br>
203
- See [LICENSE](./LICENSE).
199
+ See [LICENSE](./LICENSE)
data/lib/xchan/bytes.rb CHANGED
@@ -16,7 +16,7 @@ class Chan::Bytes
16
16
  #
17
17
  # @return [Chan::Bytes]
18
18
  def initialize(tmpdir)
19
- @io = Chan.temporary_file("xchan.bytes", tmpdir:)
19
+ @io = Chan.temporary_file(%w[bytes .json], tmpdir:)
20
20
  @io.sync = true
21
21
  write(@io, [])
22
22
  end
@@ -95,6 +95,6 @@ class Chan::Bytes
95
95
  end
96
96
 
97
97
  def deserialize(bytes)
98
- JSON.load(bytes)
98
+ JSON.parse(bytes)
99
99
  end
100
100
  end
data/lib/xchan/counter.rb CHANGED
@@ -13,7 +13,7 @@ class Chan::Counter
13
13
  #
14
14
  # @return [Chan::Counter]
15
15
  def initialize(tmpdir)
16
- @io = Chan.temporary_file("xchan.counter", tmpdir:)
16
+ @io = Chan.temporary_file(%w[counter .json], tmpdir:)
17
17
  write(@io, {"bytes_read" => 0, "bytes_written" => 0})
18
18
  end
19
19
 
@@ -57,6 +57,6 @@ class Chan::Counter
57
57
  end
58
58
 
59
59
  def deserialize(bytes)
60
- JSON.load(bytes)
60
+ JSON.parse(bytes)
61
61
  end
62
62
  end
@@ -1,5 +1,7 @@
1
- require 'delegate'
2
- require 'tmpdir'
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+ require "tmpdir"
3
5
 
4
6
  ##
5
7
  # @private
@@ -63,12 +65,12 @@ class Chan::Tempfile < DelegateClass(File)
63
65
  #
64
66
  # Related: Tempfile.create.
65
67
  #
66
- def initialize(basename="", tmpdir=nil, mode: 0, perm: 0600, **options)
68
+ def initialize(basename = "", tmpdir = nil, mode: 0, perm: 0o600, **kwargs)
67
69
  warn "Tempfile.new doesn't call the given block.", uplevel: 1 if block_given?
68
70
 
69
71
  @unlinked = false
70
- @mode = mode|File::RDWR|File::CREAT|File::EXCL
71
- ::Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
72
+ @mode = mode | File::RDWR | File::CREAT | File::EXCL
73
+ ::Dir::Tmpname.create(basename, tmpdir, **kwargs) do |tmpname, n, opts|
72
74
  @tmpfile = File.open(tmpname, @mode, perm, **opts)
73
75
  @perm = perm
74
76
  @opts = opts.freeze
@@ -81,7 +83,7 @@ class Chan::Tempfile < DelegateClass(File)
81
83
  # Opens or reopens the file with mode "r+".
82
84
  def open
83
85
  _close
84
- mode = @mode & ~(File::CREAT|File::EXCL)
86
+ mode = @mode & ~(File::CREAT | File::EXCL)
85
87
  @tmpfile = File.open(@tmpfile.path, mode, **@opts)
86
88
  __setobj__(@tmpfile)
87
89
  end
@@ -97,7 +99,7 @@ class Chan::Tempfile < DelegateClass(File)
97
99
  #
98
100
  # If you don't explicitly unlink the temporary file, the removal
99
101
  # will be delayed until the object is finalized.
100
- def close(unlink_now=false)
102
+ def close(unlink_now = false)
101
103
  _close
102
104
  unlink if unlink_now
103
105
  end
@@ -153,7 +155,7 @@ class Chan::Tempfile < DelegateClass(File)
153
155
  ObjectSpace.undefine_finalizer(self)
154
156
  @unlinked = true
155
157
  end
156
- alias delete unlink
158
+ alias_method :delete, :unlink
157
159
 
158
160
  # Returns the full path name of the temporary file.
159
161
  # This will be nil if #unlink has been called.
@@ -170,7 +172,7 @@ class Chan::Tempfile < DelegateClass(File)
170
172
  File.size(@tmpfile.path)
171
173
  end
172
174
  end
173
- alias length size
175
+ alias_method :length, :size
174
176
 
175
177
  # :stopdoc:
176
178
  def inspect
@@ -190,7 +192,7 @@ class Chan::Tempfile < DelegateClass(File)
190
192
  def call(*args)
191
193
  return if @pid != Process.pid
192
194
 
193
- $stderr.puts "removing #{@tmpfile.path}..." if $DEBUG
195
+ warn "removing #{@tmpfile.path}..." if $DEBUG
194
196
 
195
197
  @tmpfile.close
196
198
  begin
@@ -198,7 +200,7 @@ class Chan::Tempfile < DelegateClass(File)
198
200
  rescue Errno::ENOENT
199
201
  end
200
202
 
201
- $stderr.puts "done" if $DEBUG
203
+ warn "done" if $DEBUG
202
204
  end
203
205
  end
204
206
 
@@ -240,8 +242,8 @@ class Chan::Tempfile < DelegateClass(File)
240
242
  # ensure
241
243
  # f.close
242
244
  # end
243
- def self.open(*args, **kw)
244
- tempfile = new(*args, **kw)
245
+ def self.open(*args, **kwargs)
246
+ tempfile = new(*args, **kwargs)
245
247
 
246
248
  if block_given?
247
249
  begin
@@ -313,10 +315,10 @@ module Chan
313
315
  #
314
316
  # Related: Tempfile.new.
315
317
  #
316
- def Tempfile.create(basename="", tmpdir=nil, mode: 0, perm: 0600, **options)
318
+ def Tempfile.create(basename = "", tmpdir = nil, mode: 0, perm: 0o600, **kwargs)
317
319
  tmpfile = nil
318
- Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
319
- mode |= File::RDWR|File::CREAT|File::EXCL
320
+ Dir::Tmpname.create(basename, tmpdir, **kwargs) do |tmpname, n, opts|
321
+ mode |= File::RDWR | File::CREAT | File::EXCL
320
322
  tmpfile = File.open(tmpname, mode, perm, **opts)
321
323
  end
322
324
  if block_given?
@@ -325,7 +327,11 @@ module Chan
325
327
  ensure
326
328
  unless tmpfile.closed?
327
329
  if File.identical?(tmpfile, tmpfile.path)
328
- unlinked = File.unlink tmpfile.path rescue nil
330
+ unlinked = begin
331
+ File.unlink tmpfile.path
332
+ rescue
333
+ nil
334
+ end
329
335
  end
330
336
  tmpfile.close
331
337
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ##
4
- # An easy-to-use InterProcess Communication (IPC) library.
4
+ # An easy-to-use InterProcess Communication (IPC) library
5
5
  class Chan::UNIXSocket
6
6
  require "socket"
7
7
  require "lockf"
@@ -17,6 +17,12 @@ class Chan::UNIXSocket
17
17
  # Returns a socket used for write operations
18
18
  attr_reader :w
19
19
 
20
+ ##
21
+ # @return [<#dump, #load>]
22
+ # Returns the serializer used by the channel
23
+ attr_reader :s
24
+ alias_method :serializer, :s
25
+
20
26
  ##
21
27
  # @example
22
28
  # ch = Chan::UNIXSocket.new(:marshal)
@@ -24,7 +30,7 @@ class Chan::UNIXSocket
24
30
  # ch.recv.pop # => 3
25
31
  # ch.close
26
32
  #
27
- # @param [Symbol, <#dump, #load>] serializer
33
+ # @param [Symbol, <#dump, #load>] s
28
34
  # The name of a serializer
29
35
  #
30
36
  # @param [Integer] sock_type
@@ -35,19 +41,12 @@ class Chan::UNIXSocket
35
41
  #
36
42
  # @return [Chan::UNIXSocket]
37
43
  # Returns an instance of {Chan::UNIXSocket Chan::UNIXSocket}
38
- def initialize(serializer, sock_type: Socket::SOCK_DGRAM, tmpdir: Dir.tmpdir)
39
- @serializer = Chan.serializers[serializer]&.call || serializer
44
+ def initialize(s, sock_type: Socket::SOCK_DGRAM, tmpdir: Dir.tmpdir)
45
+ @s = Chan.serializers[s]&.call || s
40
46
  @r, @w = ::UNIXSocket.pair(sock_type)
41
47
  @bytes = Chan::Bytes.new(tmpdir)
42
48
  @counter = Chan::Counter.new(tmpdir)
43
- @lock = LockFile.new Chan.temporary_file("xchan.lock", tmpdir:)
44
- end
45
-
46
- ##
47
- # @return [<#dump, #load>]
48
- # Returns the serializer used by the channel
49
- def serializer
50
- @serializer
49
+ @lockf = Lock::File.new Chan.temporary_file(%w[xchan .lock], tmpdir:)
51
50
  end
52
51
 
53
52
  ##
@@ -61,15 +60,15 @@ class Chan::UNIXSocket
61
60
  # Closes the channel
62
61
  #
63
62
  # @raise [IOError]
64
- # When the channel is closed.
63
+ # When the channel is closed
65
64
  #
66
65
  # @return [void]
67
66
  def close
68
- @lock.lock
67
+ @lockf.lock
69
68
  raise IOError, "channel is closed" if closed?
70
- [@r, @w, @bytes, @lock.file].each(&:close)
69
+ [@r, @w, @bytes, @lockf].each(&:close)
71
70
  rescue IOError => ex
72
- @lock.release
71
+ @lockf.release
73
72
  raise(ex)
74
73
  end
75
74
 
@@ -112,14 +111,14 @@ class Chan::UNIXSocket
112
111
  # @return [Integer, nil]
113
112
  # Returns the number of bytes written to the channel
114
113
  def send_nonblock(object)
115
- @lock.lock_nonblock
114
+ @lockf.lock_nonblock
116
115
  raise IOError, "channel closed" if closed?
117
116
  len = @w.write_nonblock(serialize(object))
118
117
  @bytes.push(len)
119
118
  @counter.increment!(bytes_written: len)
120
- len.tap { @lock.release }
119
+ len.tap { @lockf.release }
121
120
  rescue IOError, IO::WaitWritable, Errno::ENOBUFS => ex
122
- @lock.release
121
+ @lockf.release
123
122
  raise Chan::WaitWritable, ex.message
124
123
  rescue Errno::EWOULDBLOCK => ex
125
124
  raise Chan::WaitLockable, ex.message
@@ -165,18 +164,18 @@ class Chan::UNIXSocket
165
164
  # @return [Object]
166
165
  # Returns an object from the channel
167
166
  def recv_nonblock
168
- @lock.lock_nonblock
167
+ @lockf.lock_nonblock
169
168
  raise IOError, "closed channel" if closed?
170
169
  len = @bytes.shift
171
170
  obj = deserialize(@r.read_nonblock(len.zero? ? 1 : len))
172
171
  @counter.increment!(bytes_read: len)
173
- obj.tap { @lock.release }
172
+ obj.tap { @lockf.release }
174
173
  rescue IOError => ex
175
- @lock.release
174
+ @lockf.release
176
175
  raise(ex)
177
176
  rescue IO::WaitReadable => ex
178
177
  @bytes.unshift(len)
179
- @lock.release
178
+ @lockf.release
180
179
  raise Chan::WaitReadable, ex.message
181
180
  rescue Errno::EAGAIN => ex
182
181
  raise Chan::WaitLockable, ex.message
@@ -188,9 +187,9 @@ class Chan::UNIXSocket
188
187
 
189
188
  ##
190
189
  # @example
191
- # ch = xchan
190
+ # ch = xchan(:pure)
192
191
  # 1.upto(4) { ch.send(_1) }
193
- # ch.to_a.last # => 4
192
+ # ch.to_a.last # => "4"
194
193
  #
195
194
  # @return [Array<Object>]
196
195
  # Returns the contents of the channel
@@ -229,7 +228,7 @@ class Chan::UNIXSocket
229
228
 
230
229
  ##
231
230
  # @return [Integer]
232
- # Returns the number of objects waiting to be read.
231
+ # Returns the number of objects waiting to be read
233
232
  def size
234
233
  lock { @bytes.size }
235
234
  end
@@ -241,25 +240,25 @@ class Chan::UNIXSocket
241
240
  # @group Wait methods
242
241
 
243
242
  ##
244
- # Waits for the channel to become readable.
243
+ # Waits for the channel to become readable
245
244
  #
246
245
  # @param [Float, Integer, nil] s
247
- # The number of seconds to wait. Waits indefinitely when "nil".
246
+ # The number of seconds to wait. Waits indefinitely with no arguments.
248
247
  #
249
248
  # @return [Chan::UNIXSocket, nil]
250
- # Returns self when the channel is readable, otherwise returns nil.
249
+ # Returns self when the channel is readable, otherwise returns nil
251
250
  def wait_readable(s = nil)
252
251
  @r.wait_readable(s) and self
253
252
  end
254
253
 
255
254
  ##
256
- # Waits for the channel to become writable.
255
+ # Waits for the channel to become writable
257
256
  #
258
257
  # @param [Float, Integer, nil] s
259
- # The number of seconds to wait. Waits indefinitely when "nil".
258
+ # The number of seconds to wait. Waits indefinitely with no arguments.
260
259
  #
261
260
  # @return [Chan::UNIXSocket, nil]
262
- # Returns self when the channel is writable, otherwise returns nil.
261
+ # Returns self when the channel is writable, otherwise returns nil
263
262
  def wait_writable(s = nil)
264
263
  @w.wait_writable(s) and self
265
264
  end
@@ -270,17 +269,17 @@ class Chan::UNIXSocket
270
269
  private
271
270
 
272
271
  def lock
273
- @lock.lock
272
+ @lockf.lock
274
273
  yield
275
274
  ensure
276
- @lock.release
275
+ @lockf.release
277
276
  end
278
277
 
279
278
  def serialize(obj)
280
- @serializer.dump(obj)
279
+ @s.dump(obj)
281
280
  end
282
281
 
283
282
  def deserialize(str)
284
- @serializer.load(str)
283
+ @s.load(str)
285
284
  end
286
285
  end
data/lib/xchan/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chan
4
- VERSION = "0.17.1"
4
+ VERSION = "0.18.0"
5
5
  end
data/lib/xchan.rb CHANGED
@@ -10,17 +10,14 @@ module Chan
10
10
  WaitLockable = Class.new(Errno::EWOULDBLOCK)
11
11
 
12
12
  ##
13
- # The Pure serializer won't perform
14
- # serialization that goes beyond calling
15
- # `.to_s` on the object it is given. It
16
- # can be useful when you want to communicate
17
- # purely in strings.
13
+ # Coerces an object to a string for a
14
+ # channel communicating in raw strings
15
+ # (in other words: without serialization)
18
16
  #
19
17
  # @example
20
18
  # ch = xchan(:pure)
21
- # Process.wait fork {
22
- # ch.send "Hello world"
23
- # }
19
+ # fork { ch.send "Hello world" }
20
+ # Process.wait
24
21
  # puts ch.recv
25
22
  Pure = Class.new do
26
23
  def self.dump(str) = str.to_s
@@ -47,7 +44,7 @@ module Chan
47
44
 
48
45
  ##
49
46
  # @return [Hash<Symbol, Proc>]
50
- # A mapping of serializers
47
+ # Returns the default serializers
51
48
  def self.serializers
52
49
  {
53
50
  pure: lambda { Pure },
@@ -72,11 +69,11 @@ module Kernel
72
69
  # ch.recv.pop # => 3
73
70
  # ch.close
74
71
  #
75
- # @param serializer (see Chan::UNIXSocket#initialize)
72
+ # @param s (see Chan::UNIXSocket#initialize)
76
73
  # @param sock_type (see Chan::UNIXSocket#initialize)
77
74
  # @param tmpdir (see Chan::UNIXSocket#initialize)
78
75
  # @return (see Chan::UNIXSocket#initialize)
79
- def xchan(serializer, **kw_args)
80
- Chan::UNIXSocket.new(serializer, **kw_args)
76
+ def xchan(s, ...)
77
+ Chan::UNIXSocket.new(s, ...)
81
78
  end
82
79
  end
@@ -5,13 +5,14 @@ require "xchan"
5
5
 
6
6
  $stdout.sync = true
7
7
  ch = xchan(:marshal)
8
- Process.detach fork {
8
+ fork do
9
9
  print "Received random number (child process): ", ch.recv, "\n"
10
- }
10
+ end
11
11
  sleep(1)
12
12
  print "Send a random number (from parent process)", "\n"
13
13
  ch.send(rand(21))
14
14
  ch.close
15
+ Process.wait
15
16
 
16
17
  ##
17
18
  # Send a random number (from parent process)
@@ -2,13 +2,14 @@
2
2
 
3
3
  require_relative "../setup"
4
4
  require "xchan"
5
+ require "xchan"
5
6
 
6
7
  ##
7
- # This channel uses Marshal to serialize objects
8
+ # Marshal as the serializer
8
9
  ch = xchan(:marshal)
9
10
  Process.wait fork { ch.send(5) }
10
- print "There are ", ch.recv + 7, " disciples and the same number of tribes", "\n"
11
+ print "#{ch.recv} + 7 = 12", "\n"
11
12
  ch.close
12
13
 
13
14
  ##
14
- # There are 12 disciples and the same number of tribes
15
+ # 5 + 7 = 12
data/test/readme_test.rb CHANGED
@@ -1,42 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "setup"
4
- require "test/cmd"
4
+ require "test-cmd"
5
5
 
6
6
  class Chan::ReadmeTest < Test::Unit::TestCase
7
7
  def test_serialization_1_serializers
8
- assert_equal "There are 12 disciples and the same number of tribes\n",
9
- readme_example("serialization/1_serializers.rb").stdout
8
+ assert_equal "5 + 7 = 12\n",
9
+ cmd("ruby", readme_example("serialization/1_serializers.rb")).stdout
10
10
  end
11
11
 
12
12
  def test_read_operations_1_blocking_read
13
13
  r = 'Send a random number \(from parent process\)\s*' \
14
14
  'Received random number \(child process\): \d+'
15
15
  assert_match Regexp.new(r),
16
- readme_example("read_operations/1_blocking_read.rb").stdout
17
- .tr("\n", " ")
16
+ cmd("ruby", readme_example("read_operations/1_blocking_read.rb"))
17
+ .stdout
18
+ .tr("\n", " ")
18
19
  end
19
20
 
20
21
  def test_write_operations_2_non_blocking_write
21
22
  assert_equal ["Blocked - free send buffer\n"],
22
- readme_example("write_operations/2_nonblocking_write.rb").stdout
23
- .each_line
24
- .uniq
23
+ cmd("ruby", readme_example("write_operations/2_nonblocking_write.rb"))
24
+ .stdout
25
+ .each_line
26
+ .uniq
25
27
  end
26
28
 
27
29
  def test_socket_2_options
28
30
  r = 'The read buffer can contain a maximum of: \d{1,6} bytes.\s*' \
29
31
  'The maximum size of a single message is: \d{1,6} bytes.\s*'
30
32
  assert_match Regexp.new(r),
31
- readme_example("socket/2_options.rb").stdout
32
- .tr("\n", " ")
33
+ cmd("ruby", readme_example("socket/2_options.rb"))
34
+ .stdout
35
+ .tr("\n", " ")
33
36
  end
34
37
 
35
38
  private
36
39
 
37
40
  def readme_example(path)
38
- examples_dir = File.join(Dir.getwd, "share", "xchan.rb", "examples")
39
- example = File.join(examples_dir, path)
40
- cmd "bundle exec ruby #{example}"
41
+ dir = File.join(Dir.getwd, "share", "xchan.rb", "examples")
42
+ File.join(dir, path)
41
43
  end
42
44
  end
data/test/setup.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bundler/setup"
3
4
  require "json"
4
5
  require "yaml"
5
6
  require "timeout"
data/test/xchan_test.rb CHANGED
@@ -84,7 +84,7 @@ class Chan::RecvNonBlockTest < Chan::Test
84
84
  end
85
85
 
86
86
  def test_recv_nonblock_with_a_lock
87
- ch.instance_variable_get(:@lock).lock
87
+ ch.instance_variable_get(:@lockf).lock
88
88
  pid = fork do
89
89
  ch.recv_nonblock
90
90
  exit(1)
@@ -194,3 +194,32 @@ class Chan::BytesReadTest < Chan::Test
194
194
  assert_equal object_size * 2, ch.bytes_read
195
195
  end
196
196
  end
197
+
198
+ ##
199
+ # Chan.temporary_file
200
+ class Chan::TemporaryFileTest < Chan::Test
201
+ def test_temporary_file_mode
202
+ assert_equal 0, file.stat.mode & 0o777
203
+ ensure
204
+ file.close
205
+ end
206
+
207
+ def test_temporary_file_path
208
+ assert_match %r{#{Regexp.escape(Dir.tmpdir)}/foobar[a-zA-Z0-9-]+\.txt},
209
+ file.to_path
210
+ ensure
211
+ file.close
212
+ end
213
+
214
+ def test_temporary_file_unlinked
215
+ refute File.exist?(file.to_path)
216
+ ensure
217
+ file.close
218
+ end
219
+
220
+ private
221
+
222
+ def file
223
+ @file ||= Chan.temporary_file %w[foobar .txt]
224
+ end
225
+ end
data/xchan.rb.gemspec CHANGED
@@ -12,11 +12,11 @@ Gem::Specification.new do |gem|
12
12
  gem.require_paths = ["lib"]
13
13
  gem.summary = "An easy to use InterProcess Communication (IPC) library"
14
14
  gem.description = gem.summary
15
- gem.add_runtime_dependency "lockf.rb", "~> 1.0"
15
+ gem.add_runtime_dependency "lockf.rb", "~> 2.1"
16
16
  gem.add_development_dependency "test-unit", "~> 3.5.7"
17
17
  gem.add_development_dependency "yard", "~> 0.9"
18
18
  gem.add_development_dependency "redcarpet", "~> 3.5"
19
19
  gem.add_development_dependency "standard", "~> 1.13"
20
- gem.add_development_dependency "test-cmd.rb", "~> 0.8"
20
+ gem.add_development_dependency "test-cmd.rb", "~> 0.12.4"
21
21
  gem.add_development_dependency "rake", "~> 13.1"
22
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xchan.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.1
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - '0x1eef'
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-10 00:00:00.000000000 Z
11
+ date: 2024-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lockf.rb
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '2.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: test-unit
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.8'
89
+ version: 0.12.4
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.8'
96
+ version: 0.12.4
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -117,7 +117,6 @@ extra_rdoc_files: []
117
117
  files:
118
118
  - ".github/workflows/tests.yml"
119
119
  - ".gitignore"
120
- - ".gitlab-ci.yml"
121
120
  - ".projectile"
122
121
  - ".rubocop.yml"
123
122
  - ".yardopts"
@@ -162,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
161
  - !ruby/object:Gem::Version
163
162
  version: '0'
164
163
  requirements: []
165
- rubygems_version: 3.5.9
164
+ rubygems_version: 3.5.11
166
165
  signing_key:
167
166
  specification_version: 4
168
167
  summary: An easy to use InterProcess Communication (IPC) library
data/.gitlab-ci.yml DELETED
@@ -1,12 +0,0 @@
1
- stages:
2
- - test
3
-
4
- test-ruby32:
5
- stage: test
6
- image: ruby:3.2.0
7
- script:
8
- - bundle install
9
- - SERIALIZER=marshal bundle exec rake
10
- - SERIALIZER=json bundle exec rake
11
- - SERIALIZER=yaml bundle exec rake
12
- - SERIALIZER=pure bundle exec rake