mock-thread 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|