comp_tree 0.5.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.
- data/README +153 -0
- data/Rakefile +152 -0
- data/comp_tree.gemspec +38 -0
- data/contrib/quix/Rakefile +16 -0
- data/contrib/quix/install.rb +3 -0
- data/contrib/quix/lib/quix/builtin/dir/casefold_brackets.rb +7 -0
- data/contrib/quix/lib/quix/builtin/kernel/tap.rb +9 -0
- data/contrib/quix/lib/quix/builtin/module/include.rb +21 -0
- data/contrib/quix/lib/quix/builtin/module/private.rb +41 -0
- data/contrib/quix/lib/quix/config.rb +37 -0
- data/contrib/quix/lib/quix/cygwin.rb +60 -0
- data/contrib/quix/lib/quix/diagnostic.rb +44 -0
- data/contrib/quix/lib/quix/enumerable.rb +33 -0
- data/contrib/quix/lib/quix/fileutils.rb +37 -0
- data/contrib/quix/lib/quix/hash_struct.rb +27 -0
- data/contrib/quix/lib/quix/kernel.rb +61 -0
- data/contrib/quix/lib/quix/lazy_struct.rb +55 -0
- data/contrib/quix/lib/quix/simple_installer.rb +87 -0
- data/contrib/quix/lib/quix/string.rb +38 -0
- data/contrib/quix/lib/quix/subpackager.rb +52 -0
- data/contrib/quix/lib/quix/thread_local.rb +32 -0
- data/contrib/quix/lib/quix/vars.rb +138 -0
- data/contrib/quix/lib/quix.rb +32 -0
- data/contrib/quix/test/all.rb +12 -0
- data/contrib/quix/test/test_deps.rb +25 -0
- data/contrib/quix/test/test_include.rb +47 -0
- data/contrib/quix/test/test_private.rb +86 -0
- data/contrib/quix/test/test_root.rb +19 -0
- data/contrib/quix/test/test_struct.rb +48 -0
- data/contrib/quix/test/test_vars.rb +187 -0
- data/install.rb +3 -0
- data/lib/comp_tree/algorithm.rb +210 -0
- data/lib/comp_tree/bucket_ipc.rb +151 -0
- data/lib/comp_tree/driver.rb +267 -0
- data/lib/comp_tree/error.rb +27 -0
- data/lib/comp_tree/node.rb +165 -0
- data/lib/comp_tree/quix/builtin/kernel/tap.rb +33 -0
- data/lib/comp_tree/quix/diagnostic.rb +68 -0
- data/lib/comp_tree/quix/kernel.rb +85 -0
- data/lib/comp_tree/retriable_fork.rb +42 -0
- data/lib/comp_tree/task_node.rb +22 -0
- data/lib/comp_tree.rb +23 -0
- data/test/all.rb +12 -0
- data/test/test_bucketipc.rb +72 -0
- data/test/test_circular.rb +36 -0
- data/test/test_comp_tree.rb +364 -0
- data/test/test_exception.rb +97 -0
- metadata +120 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module Quix
|
5
|
+
module Kernel
|
6
|
+
def let
|
7
|
+
yield self
|
8
|
+
end
|
9
|
+
|
10
|
+
def singleton_class
|
11
|
+
class << self
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Gensym
|
17
|
+
@mutex = Mutex.new
|
18
|
+
@count = 0
|
19
|
+
|
20
|
+
def gensym(prefix = nil)
|
21
|
+
count = Gensym.module_eval {
|
22
|
+
@mutex.synchronize {
|
23
|
+
@count += 1
|
24
|
+
}
|
25
|
+
}
|
26
|
+
"#{prefix || :G}_#{count}_#{rand}".to_sym
|
27
|
+
end
|
28
|
+
end
|
29
|
+
include Gensym
|
30
|
+
|
31
|
+
def call_private(method, *args, &block)
|
32
|
+
instance_eval { send(method, *args, &block) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def with_warnings(value = true)
|
36
|
+
previous = $VERBOSE
|
37
|
+
$VERBOSE = value
|
38
|
+
begin
|
39
|
+
yield
|
40
|
+
ensure
|
41
|
+
$VERBOSE = previous
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def no_warnings(&block)
|
46
|
+
with_warnings(false, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def abort_on_exception(value = true)
|
50
|
+
previous = Thread.abort_on_exception
|
51
|
+
Thread.abort_on_exception = value
|
52
|
+
begin
|
53
|
+
yield
|
54
|
+
ensure
|
55
|
+
Thread.abort_on_exception = previous
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
extend self
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
require 'ostruct'
|
3
|
+
require 'quix/builtin/kernel/tap'
|
4
|
+
|
5
|
+
module Quix
|
6
|
+
#
|
7
|
+
# An OpenStruct with the ability to define lazily-evaluated fields.
|
8
|
+
#
|
9
|
+
class LazyStruct < OpenStruct
|
10
|
+
#
|
11
|
+
# For mixing into an existing OpenStruct instance singleton class.
|
12
|
+
#
|
13
|
+
module Mixin
|
14
|
+
#
|
15
|
+
# &block is evaluated when this attribute is requested. The
|
16
|
+
# same result is returned for subsquent calls, until the field
|
17
|
+
# is assigned a different value.
|
18
|
+
#
|
19
|
+
def attribute(reader, &block)
|
20
|
+
singleton = (class << self ; self ; end)
|
21
|
+
singleton.instance_eval {
|
22
|
+
#
|
23
|
+
# Define a special reader method in the singleton class.
|
24
|
+
#
|
25
|
+
define_method(reader) {
|
26
|
+
block.call.tap { |value|
|
27
|
+
#
|
28
|
+
# The value has been computed. Replace this method with a
|
29
|
+
# one-liner giving the value.
|
30
|
+
#
|
31
|
+
singleton.instance_eval {
|
32
|
+
remove_method(reader)
|
33
|
+
define_method(reader) { value }
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
#
|
39
|
+
# Revert to the old OpenStruct behavior when the writer is called.
|
40
|
+
#
|
41
|
+
writer = "#{reader}=".to_sym
|
42
|
+
define_method(writer) { |value|
|
43
|
+
singleton.instance_eval {
|
44
|
+
remove_method(reader)
|
45
|
+
remove_method(writer)
|
46
|
+
}
|
47
|
+
method_missing(writer, value)
|
48
|
+
}
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
include Mixin
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'find'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'quix/vars'
|
7
|
+
|
8
|
+
module Quix
|
9
|
+
class SimpleInstaller
|
10
|
+
include Quix::Vars
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
dest_root = Config::CONFIG["sitelibdir"]
|
14
|
+
sources = []
|
15
|
+
Find.find("./lib") { |source|
|
16
|
+
if install_file?(source)
|
17
|
+
sources << source
|
18
|
+
end
|
19
|
+
}
|
20
|
+
@spec = sources.inject(Array.new) { |acc, source|
|
21
|
+
if source == "./lib"
|
22
|
+
acc
|
23
|
+
else
|
24
|
+
dest = File.join(dest_root, source.sub(%r!\A\./lib!, ""))
|
25
|
+
|
26
|
+
install = lambda {
|
27
|
+
if File.directory?(source)
|
28
|
+
unless File.directory?(dest)
|
29
|
+
puts "mkdir #{dest}"
|
30
|
+
FileUtils.mkdir(dest)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
puts "install #{source} --> #{dest}"
|
34
|
+
FileUtils.install(source, dest)
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
uninstall = lambda {
|
39
|
+
if File.directory?(source)
|
40
|
+
if File.directory?(dest)
|
41
|
+
puts "rmdir #{dest}"
|
42
|
+
FileUtils.rmdir(dest)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
if File.file?(dest)
|
46
|
+
puts "rm #{dest}"
|
47
|
+
FileUtils.rm(dest)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
}
|
51
|
+
|
52
|
+
acc << locals_to_hash {%{source, dest, install, uninstall}}
|
53
|
+
end
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def install_file?(source)
|
58
|
+
!File.symlink?(source) and
|
59
|
+
(File.directory?(source) or
|
60
|
+
(File.file?(source) and File.extname(source) == ".rb"))
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_accessor :spec
|
64
|
+
|
65
|
+
def install
|
66
|
+
@spec.each { |entry|
|
67
|
+
entry[:install].call
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def uninstall
|
72
|
+
@spec.reverse.each { |entry|
|
73
|
+
entry[:uninstall].call
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def run(args = ARGV)
|
78
|
+
if args.empty? or (args.size == 1 and args.first == "install")
|
79
|
+
install
|
80
|
+
elsif args.size == 1 and args.first == "--uninstall"
|
81
|
+
uninstall
|
82
|
+
else
|
83
|
+
raise "unrecognized arguments: #{args.inspect}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
require 'quix/builtin/kernel/tap'
|
3
|
+
|
4
|
+
module Quix
|
5
|
+
module String
|
6
|
+
def trim_left!
|
7
|
+
sub!(%r!\A\s+!, "")
|
8
|
+
end
|
9
|
+
|
10
|
+
def trim_right!
|
11
|
+
sub!(%r!\s+\Z!, "")
|
12
|
+
end
|
13
|
+
|
14
|
+
def trim!
|
15
|
+
result_left = trim_left!
|
16
|
+
result_right = trim_right!
|
17
|
+
result_left || result_right
|
18
|
+
end
|
19
|
+
|
20
|
+
def trim_left
|
21
|
+
clone.tap { |result|
|
22
|
+
result.trim_left!
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def trim_right
|
27
|
+
clone.tap { |result|
|
28
|
+
result.trim_right!
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def trim
|
33
|
+
clone.tap { |result|
|
34
|
+
result.trim!
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
require 'quix/hash_struct'
|
3
|
+
|
4
|
+
module Quix
|
5
|
+
module Subpackager
|
6
|
+
WARNING = %q{
|
7
|
+
|
8
|
+
|
9
|
+
######################################################
|
10
|
+
#
|
11
|
+
# **** DO NOT EDIT ****
|
12
|
+
#
|
13
|
+
# **** THIS IS A GENERATED FILE *****
|
14
|
+
#
|
15
|
+
######################################################
|
16
|
+
|
17
|
+
|
18
|
+
}.gsub(%r!^ +!, "")
|
19
|
+
|
20
|
+
def self.run(packages)
|
21
|
+
HashStruct.recursive_new(packages).each_pair { |pkg, pkg_spec|
|
22
|
+
pkg_spec.subpackages.each_pair { |subpkg, subpkg_spec|
|
23
|
+
process_path = lambda { |path|
|
24
|
+
source = "#{subpkg_spec.lib_dir}/#{path}.rb"
|
25
|
+
dest = "#{pkg_spec.lib_dir}/#{pkg}/#{path}.rb"
|
26
|
+
|
27
|
+
contents =
|
28
|
+
WARNING +
|
29
|
+
File.read(source).gsub(%r!require [\'\"]#{subpkg}!) {
|
30
|
+
|match|
|
31
|
+
match.sub(%r!#{subpkg}\Z!, "#{pkg}/#{subpkg}")
|
32
|
+
}.gsub(subpkg_spec.name_in_ruby) {
|
33
|
+
"#{pkg_spec.name_in_ruby}::#{subpkg_spec.name_in_ruby}"
|
34
|
+
} +
|
35
|
+
WARNING
|
36
|
+
|
37
|
+
mkdir_p(File.dirname(dest))
|
38
|
+
puts "#{source} --> #{dest}"
|
39
|
+
File.open(dest, "w") { |t| t.print(contents) }
|
40
|
+
}
|
41
|
+
|
42
|
+
unless subpkg_spec.ignore_root_rb
|
43
|
+
process_path.call(subpkg)
|
44
|
+
end
|
45
|
+
subpkg_spec.sources.each { |path|
|
46
|
+
process_path.call("#{subpkg}/#{path}")
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
require 'thread'
|
3
|
+
require 'quix/kernel'
|
4
|
+
|
5
|
+
module Quix
|
6
|
+
class ThreadLocal
|
7
|
+
include Quix::Kernel
|
8
|
+
|
9
|
+
def initialize(prefix = nil, &default)
|
10
|
+
@name = gensym(prefix)
|
11
|
+
@accessed = gensym(prefix)
|
12
|
+
@default = default
|
13
|
+
end
|
14
|
+
|
15
|
+
def value
|
16
|
+
t = Thread.current
|
17
|
+
unless t[@accessed]
|
18
|
+
if @default
|
19
|
+
t[@name] = @default.call
|
20
|
+
end
|
21
|
+
t[@accessed] = true
|
22
|
+
end
|
23
|
+
t[@name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def value=(value)
|
27
|
+
t = Thread.current
|
28
|
+
t[@accessed] = true
|
29
|
+
t[@name] = value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
|
2
|
+
require 'quix/kernel'
|
3
|
+
require 'quix/thread_local'
|
4
|
+
require 'quix/builtin/kernel/tap'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
module Quix
|
8
|
+
module Vars
|
9
|
+
include Quix::Kernel
|
10
|
+
|
11
|
+
def eval_locals(code_with_locals, &block)
|
12
|
+
code_with_locals.call.split(",").map { |name|
|
13
|
+
# trim
|
14
|
+
name.sub(%r!\A\s+!, "").sub(%r!\s+\Z!, "")
|
15
|
+
}.each { |name|
|
16
|
+
block.call(name, eval(name, code_with_locals.binding))
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def hash_to_locals(&block)
|
21
|
+
if hash = block.call
|
22
|
+
hash.each_pair { |name, value|
|
23
|
+
Vars.argument_cache.value = value
|
24
|
+
eval("#{name} = #{Vars.name}.argument_cache.value", block.binding)
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def locals_to_hash(&block)
|
30
|
+
Hash.new.tap { |hash|
|
31
|
+
eval_locals(block) { |name, value|
|
32
|
+
hash[name.to_sym] = value
|
33
|
+
}
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def config_to_hash(code)
|
38
|
+
Hash.new.tap { |hash|
|
39
|
+
each_config_pair(code) { |name, value|
|
40
|
+
hash[name] = value
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def each_config_pair(code, &block)
|
46
|
+
Vars.argument_cache.value = code
|
47
|
+
vars, bind = private__eval_config_code
|
48
|
+
vars.each { |var|
|
49
|
+
yield(var.to_sym, eval(var, bind))
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def hash_to_ivs(opts = nil, &block)
|
54
|
+
if hash = block.call
|
55
|
+
private__hash_to_ivs(
|
56
|
+
hash,
|
57
|
+
eval("self", block.binding),
|
58
|
+
opts && opts[:force])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def locals_to_ivs(opts = nil, &block)
|
63
|
+
hash = Hash.new
|
64
|
+
eval_locals(block) { |name, value|
|
65
|
+
hash[name] = value
|
66
|
+
}
|
67
|
+
private__hash_to_ivs(
|
68
|
+
hash,
|
69
|
+
eval("self", block.binding),
|
70
|
+
opts && opts[:force])
|
71
|
+
end
|
72
|
+
|
73
|
+
def with_readers(hash, *args, &block)
|
74
|
+
caller_self = eval("self", block.binding)
|
75
|
+
readers =
|
76
|
+
if args.empty?
|
77
|
+
hash.keys
|
78
|
+
else
|
79
|
+
args
|
80
|
+
end
|
81
|
+
singleton_class.instance_eval {
|
82
|
+
added = Array.new
|
83
|
+
begin
|
84
|
+
readers.each { |reader|
|
85
|
+
if caller_self.respond_to?(reader)
|
86
|
+
raise(
|
87
|
+
"Reader '#{reader}' already exists in #{caller_self.inspect}")
|
88
|
+
end
|
89
|
+
define_method(reader) {
|
90
|
+
hash[reader]
|
91
|
+
}
|
92
|
+
added << reader
|
93
|
+
}
|
94
|
+
block.call
|
95
|
+
ensure
|
96
|
+
added.each { |reader|
|
97
|
+
remove_method(reader)
|
98
|
+
}
|
99
|
+
end
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
class << self
|
106
|
+
attr_accessor :argument_cache
|
107
|
+
end
|
108
|
+
@argument_cache = ThreadLocal.new
|
109
|
+
|
110
|
+
def private__eval_config_code
|
111
|
+
eval %Q{
|
112
|
+
#{Vars.argument_cache.value}
|
113
|
+
|
114
|
+
[local_variables, binding]
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def private__hash_to_ivs(hash, target, force)
|
119
|
+
target.instance_eval {
|
120
|
+
hash.each_pair { |name, value|
|
121
|
+
ivar = "@#{name}"
|
122
|
+
unless force
|
123
|
+
existing_value = no_warnings {
|
124
|
+
instance_variable_get(ivar)
|
125
|
+
}
|
126
|
+
unless existing_value.nil?
|
127
|
+
raise "instance variable already set: #{name}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
instance_variable_set(ivar, value)
|
131
|
+
}
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
extend self
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# Convience only -- include most everything
|
3
|
+
#
|
4
|
+
|
5
|
+
root = File.dirname(__FILE__)
|
6
|
+
pkgname = File.basename(__FILE__).sub(%r!\.rb\Z!, "")
|
7
|
+
|
8
|
+
Dir["#{root}/#{pkgname}/**/*.rb"].map { |file|
|
9
|
+
# change to relative paths
|
10
|
+
file.sub(%r!\A#{root}/!, "").sub(%r!\.rb\Z!, "")
|
11
|
+
}.reject { |file|
|
12
|
+
(file =~ %r!cygwin! and RUBY_PLATFORM !~ %r!cygwin!) or
|
13
|
+
file =~ %r!builtin!
|
14
|
+
}.each { |file|
|
15
|
+
require file
|
16
|
+
}
|
17
|
+
|
18
|
+
require 'quix/builtin/kernel/tap'
|
19
|
+
|
20
|
+
%w(Config Enumerable FileUtils String).each { |name|
|
21
|
+
Kernel.const_get(name).module_eval {
|
22
|
+
include Quix.const_get(name)
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
Config.extend(Quix::Config)
|
27
|
+
|
28
|
+
class Object
|
29
|
+
include Quix::Kernel
|
30
|
+
end
|
31
|
+
|
32
|
+
include Quix
|
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
|
3
|
+
require 'quix/config'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Run in separate exec to check for missing dependencies.
|
7
|
+
#
|
8
|
+
Dir["#{File.dirname(__FILE__)}/test_*.rb"].each { |test|
|
9
|
+
unless system(Quix::Config.ruby_executable, test)
|
10
|
+
raise "test failed: #{test}"
|
11
|
+
end
|
12
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'quix/config'
|
5
|
+
|
6
|
+
class TestDeps < Test::Unit::TestCase
|
7
|
+
include Quix::Config
|
8
|
+
def test_deps
|
9
|
+
ruby = ruby_executable
|
10
|
+
root = File.expand_path("#{File.dirname(__FILE__)}/../lib")
|
11
|
+
Dir["#{root}/**/*.rb"].map { |file|
|
12
|
+
file.
|
13
|
+
sub(%r!\A#{root}/!, "").
|
14
|
+
sub(%r!\.rb\Z!, "")
|
15
|
+
}.each { |file|
|
16
|
+
unless file =~ %r!cygwin! and RUBY_PLATFORM !~ %r!cygwin!
|
17
|
+
Dir.chdir(root) {
|
18
|
+
assert(
|
19
|
+
system(ruby, "-r", file, "-e", ""),
|
20
|
+
"error requiring: '#{file}'")
|
21
|
+
}
|
22
|
+
end
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'open3'
|
5
|
+
require 'quix/config'
|
6
|
+
|
7
|
+
class TestInclude < Test::Unit::TestCase
|
8
|
+
include Quix::Config
|
9
|
+
|
10
|
+
def test_include
|
11
|
+
Dir.chdir(File.dirname(__FILE__)) {
|
12
|
+
code = %q{
|
13
|
+
$LOAD_PATH.unshift "../lib"
|
14
|
+
require 'quix/builtin/module/include'
|
15
|
+
|
16
|
+
module A
|
17
|
+
def f ; end
|
18
|
+
end
|
19
|
+
|
20
|
+
module B
|
21
|
+
def f ; end
|
22
|
+
end
|
23
|
+
|
24
|
+
module C
|
25
|
+
include A
|
26
|
+
include B
|
27
|
+
end
|
28
|
+
|
29
|
+
class D
|
30
|
+
include B
|
31
|
+
include A
|
32
|
+
end
|
33
|
+
}
|
34
|
+
ruby = ruby_executable
|
35
|
+
begin
|
36
|
+
stdin, stdout, stderr = Open3.popen3("#{ruby} -d -")
|
37
|
+
stdin.puts(code)
|
38
|
+
stdin.close_write
|
39
|
+
assert_equal(stderr.readlines,
|
40
|
+
["Note: replacing C#f with B#f\n",
|
41
|
+
"Note: replacing D#f with A#f\n"])
|
42
|
+
rescue NotImplementedError
|
43
|
+
puts "Skipping #{File.basename(__FILE__)}."
|
44
|
+
end
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'quix/config'
|
5
|
+
require 'quix/kernel'
|
6
|
+
|
7
|
+
if Quix::Config.version_ge("1.8.7")
|
8
|
+
require 'test/unit'
|
9
|
+
require 'quix/builtin/module/private'
|
10
|
+
|
11
|
+
class TestPrivate < Test::Unit::TestCase
|
12
|
+
BODY = %{
|
13
|
+
def f ; end
|
14
|
+
|
15
|
+
private {
|
16
|
+
def g ; end
|
17
|
+
def h ; end
|
18
|
+
}
|
19
|
+
|
20
|
+
def i ; end
|
21
|
+
|
22
|
+
private {
|
23
|
+
def j ; end
|
24
|
+
}
|
25
|
+
|
26
|
+
def k ; end
|
27
|
+
|
28
|
+
private {
|
29
|
+
}
|
30
|
+
|
31
|
+
def l ; end
|
32
|
+
|
33
|
+
def m ; end
|
34
|
+
def n ; end
|
35
|
+
private :m, :n
|
36
|
+
|
37
|
+
def o ; end
|
38
|
+
}
|
39
|
+
|
40
|
+
class A
|
41
|
+
eval(BODY)
|
42
|
+
end
|
43
|
+
|
44
|
+
module B
|
45
|
+
eval(BODY)
|
46
|
+
end
|
47
|
+
|
48
|
+
class C
|
49
|
+
include B
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_1
|
53
|
+
[A, C].map { |klass| klass.new }.each { |t|
|
54
|
+
assert_nothing_raised { t.f }
|
55
|
+
assert_raises(NoMethodError) { t.g }
|
56
|
+
assert_raises(NoMethodError) { t.h }
|
57
|
+
assert_nothing_raised { t.i }
|
58
|
+
assert_raises(NoMethodError) { t.j }
|
59
|
+
assert_nothing_raised { t.k }
|
60
|
+
assert_nothing_raised { t.l }
|
61
|
+
assert_raises(NoMethodError) { t.m }
|
62
|
+
assert_raises(NoMethodError) { t.n }
|
63
|
+
assert_nothing_raised { t.o }
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_2
|
68
|
+
added = []
|
69
|
+
Class.new {
|
70
|
+
extend(Quix::Kernel).singleton_class.instance_eval {
|
71
|
+
define_method(:method_added) { |name|
|
72
|
+
added << name
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
private {
|
77
|
+
def f ; end
|
78
|
+
}
|
79
|
+
|
80
|
+
def g ; end
|
81
|
+
}
|
82
|
+
assert_equal([:f, :g], added)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
|
3
|
+
require 'quix'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class TestRoot < Test::Unit::TestCase
|
7
|
+
def test_1
|
8
|
+
assert_equal(class << self ; self ; end, singleton_class)
|
9
|
+
assert_equal("moo", "moo".tap { |t| t*2 })
|
10
|
+
assert_equal("moomoo", "moo".let { |t| t*2 })
|
11
|
+
assert_equal("zzz", " zzz ".trim)
|
12
|
+
assert_nothing_raised {
|
13
|
+
ThreadLocal.new
|
14
|
+
LazyStruct.new
|
15
|
+
HashStruct.new
|
16
|
+
Config.ruby_executable
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|