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.
@@ -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.
@@ -0,0 +1,4 @@
1
+ mock-thread
2
+ ===========
3
+
4
+ Use Fibers to test Thread code
@@ -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,3 @@
1
+ module MockThread
2
+ VERSION = "0.1"
3
+ 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: