mock-thread 0.1
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 +7 -0
- data/COPYING +22 -0
- data/README.md +4 -0
- data/Rakefile +65 -0
- data/lib/mock-thread/mock-queue.rb +42 -0
- data/lib/mock-thread/mock-thread.rb +103 -0
- data/lib/mock-thread/version.rb +3 -0
- data/test/test-mock-queue.rb +93 -0
- data/test/test-mock-thread.rb +93 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 281c06e996f0ecee2b850ec80a6a01ad49959d2d
|
4
|
+
data.tar.gz: 234cfa97de1a6a42edca8ea87ffbabac9207bbe8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5d9fb91bfe79f17557b7da312ed1d841ad3359f0b0d051f07b09c4a0a97a3dc805292b357044bcc2b017d78ee685955eab07f7c5ea090f708c01c36182258a55
|
7
|
+
data.tar.gz: 99a1ff15e91b629c893aa02f7300655ddb3fffa044e675bb51b6f8f2565077b5d81cf2a6ca5f177b77862a04368c078ec92cb8212a8051039f87742a45cab531
|
data/COPYING
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014, Joel VanderWerf, vjoel@users.sourceforge.net
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
17
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
18
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
19
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
20
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
21
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
22
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
PRJ = "mock-thread"
|
5
|
+
|
6
|
+
def version
|
7
|
+
@version ||= begin
|
8
|
+
require 'mock-thread/version'
|
9
|
+
warn "MockThread::VERSION not a string" unless
|
10
|
+
MockThread::VERSION.kind_of? String
|
11
|
+
MockThread::VERSION
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def tag
|
16
|
+
@tag ||= "#{PRJ}-#{version}"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Run tests"
|
20
|
+
Rake::TestTask.new :test do |t|
|
21
|
+
t.libs << "lib"
|
22
|
+
t.libs << "ext"
|
23
|
+
t.test_files = FileList["test/**/*.rb"]
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Commit, tag, and push repo; build and push gem"
|
27
|
+
task :release => "release:is_new_version" do
|
28
|
+
require 'tempfile'
|
29
|
+
|
30
|
+
sh "gem build #{PRJ}.gemspec"
|
31
|
+
|
32
|
+
file = Tempfile.new "template"
|
33
|
+
begin
|
34
|
+
file.puts "release #{version}"
|
35
|
+
file.close
|
36
|
+
sh "git commit --allow-empty -a -v -t #{file.path}"
|
37
|
+
ensure
|
38
|
+
file.close unless file.closed?
|
39
|
+
file.unlink
|
40
|
+
end
|
41
|
+
|
42
|
+
sh "git tag #{tag}"
|
43
|
+
sh "git push"
|
44
|
+
sh "git push --tags"
|
45
|
+
|
46
|
+
sh "gem push #{tag}.gem"
|
47
|
+
end
|
48
|
+
|
49
|
+
namespace :release do
|
50
|
+
desc "Diff to latest release"
|
51
|
+
task :diff do
|
52
|
+
latest = `git describe --abbrev=0 --tags --match '#{PRJ}-*'`.chomp
|
53
|
+
sh "git diff #{latest}"
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Log to latest release"
|
57
|
+
task :log do
|
58
|
+
latest = `git describe --abbrev=0 --tags --match '#{PRJ}-*'`.chomp
|
59
|
+
sh "git log #{latest}.."
|
60
|
+
end
|
61
|
+
|
62
|
+
task :is_new_version do
|
63
|
+
abort "#{tag} exists; update version!" unless `git tag -l #{tag}`.empty?
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class MockQueue
|
2
|
+
class QueueEmptyError < StandardError; end
|
3
|
+
|
4
|
+
attr_reader :entries
|
5
|
+
attr_reader :yield_on_push
|
6
|
+
attr_reader :yield_on_pop
|
7
|
+
|
8
|
+
def initialize yield_on_push: false, yield_on_pop: false
|
9
|
+
@entries = []
|
10
|
+
@yield_on_push = yield_on_push
|
11
|
+
@yield_on_pop = yield_on_pop
|
12
|
+
end
|
13
|
+
|
14
|
+
def empty?
|
15
|
+
entries.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
def push val
|
19
|
+
@entries << val
|
20
|
+
if yield_on_push
|
21
|
+
Fiber.yield([:push, val]) rescue FiberError
|
22
|
+
end
|
23
|
+
end
|
24
|
+
alias << push
|
25
|
+
|
26
|
+
def pop
|
27
|
+
begin
|
28
|
+
while @entries.empty?
|
29
|
+
Fiber.yield :block
|
30
|
+
end
|
31
|
+
rescue FiberError => ex
|
32
|
+
raise QueueEmptyError, "queue empty (#{ex.message})"
|
33
|
+
end
|
34
|
+
|
35
|
+
val = @entries.shift
|
36
|
+
if yield_on_pop
|
37
|
+
Fiber.yield([:pop, val]) rescue FiberError
|
38
|
+
end
|
39
|
+
val
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'fiber'
|
2
|
+
|
3
|
+
require 'mock-thread/mock-queue.rb'
|
4
|
+
|
5
|
+
class MockThread
|
6
|
+
class IsBlocked < RuntimeError; end
|
7
|
+
class IsDone < RuntimeError; end
|
8
|
+
|
9
|
+
def make_queue
|
10
|
+
MockQueue.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Override to update any state before running a step. For example, update
|
14
|
+
# part of the system that is not expressed by a mock thread, such as
|
15
|
+
# a component that processes what mock threads have sent to a queue.
|
16
|
+
def update_before; end
|
17
|
+
|
18
|
+
# Override to update any state after running a step.
|
19
|
+
def update_after; end
|
20
|
+
|
21
|
+
# Schedule some code for deferred execution. For example:
|
22
|
+
#
|
23
|
+
# c.will {foo}.will {bar}
|
24
|
+
#
|
25
|
+
# The #foo and #bar methods of c will be called later.
|
26
|
+
#
|
27
|
+
def will &block
|
28
|
+
(@will_do ||= []) << Fiber.new { instance_eval &block }
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def step
|
33
|
+
loop do
|
34
|
+
fiber = @will_do[0] or raise IsDone, "nothing to do"
|
35
|
+
|
36
|
+
if fiber.alive?
|
37
|
+
update_before
|
38
|
+
val = fiber.resume
|
39
|
+
update_after
|
40
|
+
return val
|
41
|
+
end
|
42
|
+
|
43
|
+
@will_do.shift
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def run limit: 100
|
48
|
+
loop do
|
49
|
+
fiber = @will_do[0] or raise IsDone, "nothing to do"
|
50
|
+
|
51
|
+
count = 0
|
52
|
+
while fiber.alive?
|
53
|
+
update_before
|
54
|
+
val = fiber.resume
|
55
|
+
update_after
|
56
|
+
if fiber.alive? or @will_do.size > 1
|
57
|
+
if val == :block
|
58
|
+
count += 1
|
59
|
+
if count > limit
|
60
|
+
raise IsBlocked, "exceeded blocking limit"
|
61
|
+
end
|
62
|
+
else
|
63
|
+
count = 0
|
64
|
+
yield val if block_given?
|
65
|
+
end
|
66
|
+
else
|
67
|
+
return val
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
@will_do.shift
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_until_blocked limit: 100, &block
|
76
|
+
begin
|
77
|
+
run limit: limit, &block
|
78
|
+
rescue IsBlocked
|
79
|
+
return
|
80
|
+
end
|
81
|
+
raise IsDone, "run_until_blocked never blocked"
|
82
|
+
end
|
83
|
+
|
84
|
+
def now limit: 100, &block
|
85
|
+
fiber = Fiber.new { instance_eval &block }
|
86
|
+
val = nil
|
87
|
+
count = 0
|
88
|
+
update_before
|
89
|
+
while fiber.alive?
|
90
|
+
val = fiber.resume
|
91
|
+
if val == :block
|
92
|
+
count += 1
|
93
|
+
if count > limit
|
94
|
+
raise IsBlocked, "cannot now do that -- exceeded blocking limit"
|
95
|
+
end
|
96
|
+
else
|
97
|
+
count = 0
|
98
|
+
end
|
99
|
+
update_after
|
100
|
+
end
|
101
|
+
val
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
require 'mock-thread/mock-queue.rb'
|
4
|
+
|
5
|
+
class TestMockQueueWithPushPopYields < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@q = MockQueue.new yield_on_push: true, yield_on_pop: true
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_push
|
11
|
+
f = Fiber.new do |val|
|
12
|
+
loop do
|
13
|
+
val = @q.push val
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
a = []
|
18
|
+
assert_equal a, @q.entries
|
19
|
+
|
20
|
+
3.times do |i|
|
21
|
+
op, val = f.resume i
|
22
|
+
assert_equal :push, op
|
23
|
+
assert_equal i, val
|
24
|
+
a << i
|
25
|
+
assert_equal a, @q.entries
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_pop
|
30
|
+
a = []
|
31
|
+
f = Fiber.new do
|
32
|
+
loop do
|
33
|
+
a << @q.pop
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
3.times do
|
38
|
+
op = f.resume
|
39
|
+
assert_equal :block, op
|
40
|
+
assert_equal [], a
|
41
|
+
end
|
42
|
+
|
43
|
+
@q.entries.concat (0...10).to_a
|
44
|
+
|
45
|
+
10.times do |i|
|
46
|
+
op, val = f.resume
|
47
|
+
assert_equal :pop, op
|
48
|
+
assert_equal i, val
|
49
|
+
end
|
50
|
+
|
51
|
+
op = f.resume
|
52
|
+
assert_equal :block, op
|
53
|
+
assert_equal a, (0...10).to_a
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class TestMockQueueSimpler < Minitest::Test
|
58
|
+
def setup
|
59
|
+
@q = MockQueue.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_push
|
63
|
+
a = []
|
64
|
+
assert_equal a, @q.entries
|
65
|
+
|
66
|
+
3.times do |i|
|
67
|
+
@q.push i
|
68
|
+
a << i
|
69
|
+
assert_equal a, @q.entries
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_pop
|
74
|
+
a = []
|
75
|
+
f = Fiber.new do
|
76
|
+
loop do
|
77
|
+
a << @q.pop
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
3.times do
|
82
|
+
op = f.resume
|
83
|
+
assert_equal :block, op
|
84
|
+
assert_equal [], a
|
85
|
+
end
|
86
|
+
|
87
|
+
@q.entries.concat (0...10).to_a
|
88
|
+
|
89
|
+
op = f.resume
|
90
|
+
assert_equal :block, op
|
91
|
+
assert_equal a, (0...10).to_a
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
require 'mock-thread/mock-thread.rb'
|
4
|
+
|
5
|
+
class TestMockThread < Minitest::Test
|
6
|
+
def test_step
|
7
|
+
mt = MockThread.new
|
8
|
+
|
9
|
+
mt.will do
|
10
|
+
3.times do |i|
|
11
|
+
Fiber.yield i
|
12
|
+
end
|
13
|
+
"done"
|
14
|
+
end
|
15
|
+
|
16
|
+
assert_equal 0, mt.step
|
17
|
+
assert_equal 1, mt.step
|
18
|
+
assert_equal 2, mt.step
|
19
|
+
assert_equal "done", mt.step
|
20
|
+
assert_raises MockThread::IsDone do
|
21
|
+
mt.step
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_run
|
26
|
+
mt = MockThread.new
|
27
|
+
|
28
|
+
mt.will do
|
29
|
+
3.times do |i|
|
30
|
+
Fiber.yield i
|
31
|
+
end
|
32
|
+
"done"
|
33
|
+
end
|
34
|
+
|
35
|
+
a = []
|
36
|
+
r = mt.run do |val|
|
37
|
+
a << val
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_equal "done", r
|
41
|
+
assert_equal [0,1,2], a
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_run_until_blocked
|
45
|
+
mt = MockThread.new
|
46
|
+
|
47
|
+
mt.will do
|
48
|
+
3.times do |i|
|
49
|
+
Fiber.yield i
|
50
|
+
end
|
51
|
+
11.times do
|
52
|
+
Fiber.yield :block
|
53
|
+
end
|
54
|
+
"done"
|
55
|
+
end
|
56
|
+
|
57
|
+
a = []
|
58
|
+
mt.run_until_blocked limit:10 do |val|
|
59
|
+
a << val
|
60
|
+
end
|
61
|
+
|
62
|
+
assert_equal [0,1,2], a
|
63
|
+
|
64
|
+
r = mt.run
|
65
|
+
assert_equal "done", r
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_now
|
69
|
+
mt = MockThread.new
|
70
|
+
|
71
|
+
result = mt.now do
|
72
|
+
3.times do
|
73
|
+
Fiber.yield :block
|
74
|
+
end
|
75
|
+
"done"
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal "done", result
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_now_limit
|
82
|
+
mt = MockThread.new
|
83
|
+
|
84
|
+
assert_raises MockThread::IsBlocked do
|
85
|
+
mt.now limit: 2 do
|
86
|
+
3.times do
|
87
|
+
Fiber.yield :block
|
88
|
+
end
|
89
|
+
"done"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mock-thread
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joel VanderWerf
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Use Fibers to test Thread code.
|
14
|
+
email: vjoel@users.sourceforge.net
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files:
|
18
|
+
- README.md
|
19
|
+
- COPYING
|
20
|
+
files:
|
21
|
+
- COPYING
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- lib/mock-thread/mock-queue.rb
|
25
|
+
- lib/mock-thread/mock-thread.rb
|
26
|
+
- lib/mock-thread/version.rb
|
27
|
+
- test/test-mock-queue.rb
|
28
|
+
- test/test-mock-thread.rb
|
29
|
+
homepage: https://github.com/vjoel/mock-thread
|
30
|
+
licenses:
|
31
|
+
- BSD
|
32
|
+
metadata: {}
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options:
|
35
|
+
- "--quiet"
|
36
|
+
- "--line-numbers"
|
37
|
+
- "--inline-source"
|
38
|
+
- "--title"
|
39
|
+
- MockThread
|
40
|
+
- "--main"
|
41
|
+
- README.md
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.2.2
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Use Fibers to test Thread code
|
60
|
+
test_files:
|
61
|
+
- test/test-mock-thread.rb
|
62
|
+
- test/test-mock-queue.rb
|
63
|
+
has_rdoc:
|