xchan.rb 0.17.1 → 0.18.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.
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