rubuild-core 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,117 @@
1
+ module Rubuild
2
+ module Load
3
+ ## Rubuild::Load::NameSpace
4
+ # Manage private execution contexts.
5
+ #
6
+ # Rubuild::Load::NameSpace creates private execution contexts.
7
+ # These contexts are sub-classed from Rubuild::Load::NameSpace::Context,
8
+ # and as such they can access information about how they were loaded
9
+ # through the Rubuild::Load::NameSpace::Context.rubuild_info method by
10
+ # calling Rubuild::Load::NameSpace::Context.rubuild_info.
11
+ class NameSpace
12
+
13
+ ## Rubuild::Load::NameSpace::Context
14
+ # Superclass of private execution context classes.
15
+ # Provides rubuild_info accessor routines.
16
+ class Context
17
+
18
+ ## Rubuild::Load::NameSpace::Context::Error
19
+ # Superclass of errors generated in context processing.
20
+ class Error < StandardError
21
+ # Private execution context against which the error was generated.
22
+ Safer::IVar.instance_variable(self, :context)
23
+ Safer::IVar.export_reader(self, :context)
24
+
25
+ # Create a new Rubuild::Load::NameSpace::Context::Error exception.
26
+ # [+context+] Private execution context associated with the exception.
27
+ # [+message+] Human-readable string describing the exception.
28
+ def initialize(context, message)
29
+ super(message)
30
+ self.rubuild_load_namespace_context_error__context = context
31
+ end # Rubuild::Load::NameSpace::Context::Error#initialize
32
+
33
+ ## Rubuild::Load::NameSpace::Context::Error::InstanceMethod
34
+ # Defined an instance method of private class with no instance.
35
+ class InstanceMethod < Rubuild::Load::NameSpace::Context::Error
36
+ # Name of new method.
37
+ Safer::IVar.instance_variable(self, :meth)
38
+ Safer::IVar.export_reader(self, :meth)
39
+
40
+ # Create a new Rubuild::Load::NameSpace::Context::Error::InstanceMethod
41
+ # exception.
42
+ # [+context+] Private execution context in which a user attempted
43
+ # to define a method.
44
+ # [+meth+] Name of method the user attempted to define.
45
+ def initialize(context, meth)
46
+ super(
47
+ context,
48
+ "Defined instance method :#{meth} of private class with no " +
49
+ "instance."
50
+ )
51
+ self.rubuild_load_namespace_context_error_instancemethod__meth = meth
52
+ end # Rubuild::Load::NameSpace::Context::Error::InstanceMethod#initialize
53
+ end # Rubuild::Load::NameSpace::Context::Error::InstanceMethod
54
+ end # Rubuild::Load::NameSpace::Context::Error
55
+
56
+ ## Rubuild::Load::NameSpace::Context
57
+
58
+ # Set the load-environment information for a Rubuild::Load::NameSpace::Context
59
+ # subclass.
60
+ # Every Rubuild::Load::NameSpace executes in a unique private subclass of
61
+ # Rubuild::Load::NameSpace::Context, so this class method can be called by
62
+ # code within the namespace to set information about the load environment.
63
+ # Used internally directly after creating a new Rubuild::Load::NameSpace.
64
+ # [+info+] New load-environment information for a
65
+ # Rubuild::Load::NameSpace::Context subclass.
66
+ def self.rubuild_info=(info)
67
+ # Note: this object is the 'Context' instance of the 'Class' class.
68
+ # This is as opposed to a variable instance of the 'Context' class.
69
+ # We can use @instance_variable uniquely in this class.
70
+ @rubuild_info = info
71
+ end # Rubuild::Load::NameSpace::Context.rubuild_info=
72
+
73
+ # Retrieve the load-environment information for a
74
+ # Rubuild::Load::NameSpace::Context subclass.
75
+ # Every Rubuild::Load::NameSpace executes in a unique private subclass of
76
+ # Rubuild::Load::NameSpace::Context, so this class method can be called by
77
+ # code within the namespace to set information about the load environment.
78
+ # Calling
79
+ # self.rubuild_info
80
+ # retrieves information about the Rubuild::Load::NameSpace that was set when
81
+ # the Rubuild::Load::NameSpace was created.
82
+ def self.rubuild_info
83
+ # see above.
84
+ @rubuild_info
85
+ end # Rubuild::Load::NameSpace::Context.rubuild_info
86
+
87
+ # Override Class#method_added to raise an exception, and prevent users
88
+ # from defining functions that they will not then be able to call.
89
+ def self.method_added(meth)
90
+ raise(Error::InstanceMethod.new(self, meth))
91
+ end # Rubuild::Load::NameSpace::Context.method_added
92
+ end # Rubuild::Load::NameSpace::Context
93
+
94
+ ## Rubuild::Load::NameSpace::Factory
95
+ class Factory
96
+ # parent class of private exectuion contexts.
97
+ Safer::IVar.instance_variable(self, :load_class)
98
+ Safer::IVar.export_reader(self, :load_class)
99
+
100
+ # Create an private execution context factory.
101
+ # Execution contexts will be created on demand, from
102
+ # Rubuild::Load::NameSpace::Factory#create.
103
+ # [+load_class+] Superclass of private classes used for execution.
104
+ def initialize(load_class = Rubuild::Load::NameSpace::Context)
105
+ self.rubuild_load_namespace_factory__load_class = load_class
106
+ end # Rubuild::Load::NameSpace::Factory#initialize
107
+
108
+ # Create a private execution context, and return it.
109
+ # [_return_] A newly created private execution context, sub-classed from
110
+ # Rubuild::Load::NameSpace#load_class.
111
+ def create
112
+ Class.new(self.rubuild_load_namespace_factory__load_class)
113
+ end # Rubuild::Load::NameSpace::Factory#create
114
+ end # Rubuild::Load::NameSpace::Factory
115
+ end # Rubuild::Load::NameSpace
116
+ end # Rubuild::Load
117
+ end # Rubuild
@@ -0,0 +1,34 @@
1
+ require 'optparse'
2
+
3
+ module Rubuild
4
+ ## Rubuild::Options
5
+ # Command-line processing.
6
+ class Options
7
+ Safer::IVar.instance_variable(self, :inc_paths)
8
+ Safer::IVar.export_reader(self, :inc_paths)
9
+ Safer::IVar.instance_variable(self, :file)
10
+ Safer::IVar.export_reader(self, :file)
11
+ Safer::IVar.instance_variable(self, :args_left)
12
+ Safer::IVar.export_reader(self, :args_left)
13
+ def initialize(args)
14
+ self.rubuild_options__inc_paths = []
15
+ self.rubuild_options__file = 'Rutop'
16
+ self.rubuild_options__args_left = args.dup
17
+
18
+ OptionParser.new do |opts|
19
+ opts.banner = 'Usage: rubuild [options]'
20
+ opts.separator ''
21
+ opts.on(
22
+ '-f', '--file FILE',
23
+ "Run Rubuild script from FILE. Defaults to #{self.file}") do |file|
24
+ self.rubuild_options__file = file
25
+ end
26
+ opts.on(
27
+ '-I', '--include-path PATH',
28
+ 'Add PATH to the list of directories to search for Rubuild files.') do |path|
29
+ self.rubuild_options__inc_paths << path
30
+ end
31
+ end.order!(self.rubuild_options__args_left)
32
+ end
33
+ end # Rubuild::Options
34
+ end # Rubuild
@@ -0,0 +1,11 @@
1
+ module Rubuild
2
+ module Util
3
+ def self.enumerable_find(enum, ifnone=nil)
4
+ rv = nil
5
+ enum.find do |el|
6
+ rv = yield el
7
+ end
8
+ rv || ifnone
9
+ end
10
+ end # Rubuild::Util
11
+ end # Rubuild
@@ -0,0 +1,176 @@
1
+ require 'rubuild'
2
+ require 'test/unit'
3
+
4
+ class TC_DepOrder < Test::Unit::TestCase
5
+ class TestDep
6
+ attr_reader :extra_args
7
+
8
+ def initialize(key, output)
9
+ @TestDep_key = key
10
+ @output = output
11
+ @extra_args = nil
12
+ end
13
+
14
+ def call(dep, *extra_args)
15
+ @output << self.display
16
+ if extra_args.size > 0
17
+ @extra_args = extra_args
18
+ end
19
+ end
20
+ def display
21
+ @TestDep_key
22
+ end
23
+ end
24
+
25
+ def setup
26
+ @rctx = Rubuild::Build::Simple::Factory.new
27
+ @output = Array::new
28
+ @tdeps =
29
+ Array.new(4) do |index|
30
+ TestDep::new(index.to_s, @output)
31
+ end
32
+ @deps =
33
+ Array.new(@tdeps.size) do |index|
34
+ @rctx.create_dep(@tdeps[index], @tdeps[index].display)
35
+ end
36
+ end
37
+
38
+ def teardown
39
+ @rctx = nil
40
+ @output = nil
41
+ @deps = nil
42
+ end
43
+
44
+ def create_dep_tree
45
+ @deps[1].add_parent(@deps[0])
46
+ @deps[2].add_parent(@deps[1])
47
+ @deps[3].add_parent(@deps[0])
48
+ @deps[3].add_parent(@deps[2])
49
+ end
50
+
51
+ def array_compare(array1, array2)
52
+ assert(array1.size == array2.size)
53
+ array1.size.times do |index|
54
+ assert(array1[index] == array2[index])
55
+ end
56
+ end
57
+
58
+ def test_partial_build
59
+ self.create_dep_tree
60
+ bctx = @rctx.create_context
61
+ @deps[1].load(bctx)
62
+ bctx.run
63
+ self.array_compare(@output, ['0', '1'])
64
+ @deps[2].load(bctx)
65
+ self.array_compare(@output, ['0', '1'])
66
+ bctx.run
67
+ self.array_compare(@output, ['0', '1', '2'])
68
+ @deps[3].load(bctx)
69
+ bctx.run
70
+ self.array_compare(@output, ['0', '1', '2', '3'])
71
+ end
72
+
73
+ def test_dep_loop1
74
+ self.assert_raise(Rubuild::Build::Dep::Error::Load) do
75
+ self.create_dep_tree
76
+ @deps[0].add_parent(@deps[3])
77
+ end
78
+ end
79
+
80
+ def test_dep_loop2
81
+ self.assert_raise(Rubuild::Build::Dep::Error::Load) do
82
+ self.create_dep_tree
83
+ @deps[0].add_parent(@deps[3])
84
+ end
85
+ end
86
+
87
+ def test_nil_cmds
88
+ self.create_dep_tree
89
+ bctx = @rctx.create_context
90
+ @deps[2].set_command(nil)
91
+ @deps[3].load(bctx)
92
+ bctx.run
93
+ self.array_compare(@output, ['0', '1', '3'])
94
+ end
95
+
96
+ def test_extra_args
97
+ self.create_dep_tree
98
+ bctx = @rctx.create_context
99
+ extraargs = ['hello', 'world']
100
+ @deps[2].args = extraargs
101
+ assert(@tdeps[2].extra_args == nil)
102
+ @deps[3].load(bctx)
103
+ assert(@tdeps[2].extra_args == nil)
104
+ bctx.run
105
+ self.array_compare(@tdeps[2].extra_args, extraargs)
106
+ end
107
+
108
+ def parameter_assertion(dep, errortype, parameter)
109
+ self.assert_block do
110
+ rval = false
111
+ begin
112
+ yield
113
+ rescue errortype
114
+ if $!.dep == dep and $!.parameter == parameter
115
+ rval = true
116
+ end
117
+ end
118
+ rval
119
+ end
120
+ self.assert_raise(errortype) do
121
+ yield
122
+ end
123
+ end
124
+
125
+ def test_loaded_actions
126
+ bctx = @rctx.create_context
127
+ @deps[1].load(bctx)
128
+ self.assert_block do
129
+ rval = false
130
+ begin
131
+ @deps[1].add_parent(@deps[0])
132
+ rescue Rubuild::Build::Dep::Error::Runable
133
+ if $!.dep == @deps[1] and $!.parent == @deps[0]
134
+ rval = true
135
+ end
136
+ end
137
+ rval
138
+ end
139
+
140
+ self.parameter_assertion(
141
+ @deps[1], Rubuild::Build::Dep::Error::Parameter::Args, 'args'
142
+ ) do
143
+ @deps[1].args = ['foo']
144
+ end
145
+
146
+ self.parameter_assertion(
147
+ @deps[1], Rubuild::Build::Dep::Error::Parameter::Command, 'command'
148
+ ) do
149
+ @deps[1].set_command(nil)
150
+ end
151
+ end
152
+
153
+ def test_surrogate
154
+ testarr = Array::new
155
+ surr = proc do |dep, count|
156
+ testarr << count
157
+ if count > 0
158
+ count -= 1
159
+ ndep = @rctx.create_dep(surr, "#{count}", count)
160
+ dep.surrogate(ndep)
161
+ end
162
+ end
163
+ d1 = @rctx.create_dep(surr, 'loop', 3)
164
+ child = proc do |dep|
165
+ testarr << -1
166
+ end
167
+ d2 = @rctx.create_dep(child, 'child')
168
+ d2.add_parent(d1)
169
+
170
+ bctx = @rctx.create_context
171
+ self.array_compare(testarr, Array::new)
172
+ d2.load(bctx)
173
+ bctx.run
174
+ self.array_compare(testarr, [3, 2, 1, 0, -1])
175
+ end
176
+ end
@@ -0,0 +1,91 @@
1
+ require 'rubuild'
2
+ require 'test/unit'
3
+
4
+ class TC_Env < Test::Unit::TestCase
5
+ def setup
6
+ @depfactory = Rubuild::Build::Simple::Factory.new
7
+ @env = Rubuild::Env.new(@depfactory)
8
+ end
9
+
10
+ def teardown
11
+ @depfactory = nil
12
+ @env = nil
13
+ end
14
+
15
+ def test_errorGeneration
16
+ error = Rubuild::Env::Error.new(@env, "test error class")
17
+ assert_same(@env, error.env)
18
+ assert_equal("test error class", error.message)
19
+ end
20
+
21
+ def test_errorKeyGeneration
22
+ error = Rubuild::Env::Error::Key.new(@env, 'foo', 'test error message')
23
+ assert_same(@env, error.env)
24
+ assert_equal('foo', error.key)
25
+ assert_equal(error.message, 'test error message')
26
+ end
27
+
28
+ def test_errorFullGeneration
29
+ l1 = Rubuild::Env::Location.new('foo', @depfactory)
30
+ l2 = Rubuild::Env::Location.new('bar', @depfactory)
31
+ error = Rubuild::Env::Error::Key::Full.new(@env, 'foo', l1, l2)
32
+ assert_same(@env, error.env)
33
+ assert_same(l1, error.provided_location)
34
+ assert_same(l2, error.providing_location)
35
+ assert_equal(
36
+ "Key \"foo\" already exists in registry at #{l1.found_dep.name} " +
37
+ "while providing #{l2.found_dep.name}",
38
+ error.message)
39
+ end
40
+
41
+ def test_errorEmptyGeneration
42
+ l = Rubuild::Env::Location.new('foo', @depfactory)
43
+ error = Rubuild::Env::Error::Key::Empty.new(@env, 'foo', l)
44
+ assert_same(@env, error.env)
45
+ assert_same(l, error.requiring_location)
46
+ assert_equal('foo', error.key)
47
+ assert_equal(
48
+ "Key \"foo\" does not exist in registry for #{l.found_dep.name}.",
49
+ error.message)
50
+ end
51
+
52
+ def test_requireEmptyRaisesKeyEmpty
53
+ l = Rubuild::Env::Location.new('bar', @depfactory)
54
+ @env.require('foo', l)
55
+ fail "no error raised"
56
+ rescue Rubuild::Env::Error::Key::Empty => error
57
+ assert_equal('foo', error.key)
58
+ rescue Exception
59
+ fail "wrong error raised"
60
+ end
61
+
62
+ def test_provideThenRequireRaisesNoExceptions
63
+ l1 = Rubuild::Env::Location.new('foo', @depfactory)
64
+ l2 = Rubuild::Env::Location.new('bar', @depfactory)
65
+ @env.provide('foo', l1)
66
+ @env.require('foo', l2)
67
+ end
68
+
69
+ def test_provideTwiceRaisesKeyFull
70
+ l1 = Rubuild::Env::Location.new('foo', @depfactory)
71
+ @env.provide('foo', l1)
72
+ @env.provide('foo', l1)
73
+ fail "no error raised"
74
+ rescue Rubuild::Env::Error::Key::Full => error
75
+ assert_equal('foo', error.key)
76
+ rescue Exception
77
+ fail "wrong error raised"
78
+ end
79
+
80
+ def test_requireProvidedDataGetsData
81
+ l1 = Rubuild::Env::Location.new('foo', @depfactory)
82
+ l1.set_data('hello')
83
+ l2 = Rubuild::Env::Location.new('bar', @depfactory)
84
+ @env.provide('key', l1)
85
+ @env.require('key', l2)
86
+ bctx = @depfactory.create_context
87
+ l2.found_dep.load(bctx)
88
+ bctx.run
89
+ assert_equal('hello', l2.data)
90
+ end
91
+ end
@@ -0,0 +1,68 @@
1
+ require 'rubuild'
2
+ require 'test/unit'
3
+
4
+ class TC_Location < Test::Unit::TestCase
5
+ def setup
6
+ @depfactory = Rubuild::Build::Simple::Factory.new
7
+ @location = Rubuild::Env::Location.new('location', @depfactory)
8
+ end
9
+ def teardown
10
+ end
11
+
12
+ def test_locationEmpty
13
+ bctx = @depfactory.create_context
14
+ @location.found_dep.load(bctx)
15
+ begin
16
+ begin
17
+ bctx.run
18
+ rescue Rubuild::Build::Dep::Error::Action => e
19
+ raise e.error
20
+ end
21
+ flunk("Should have raised an exception.")
22
+ rescue Rubuild::Env::Location::Error::BuiltEmpty => e
23
+ assert_same(e.location, @location)
24
+ end
25
+ end
26
+
27
+ def test_haveDataIsFalseAtFirst
28
+ assert(! @location.have_data)
29
+ end
30
+
31
+ def test_haveDataIsTrueAfterSetData
32
+ @location.set_data(:hello)
33
+ assert(@location.have_data)
34
+ end
35
+
36
+ def test_locationEarly
37
+ begin
38
+ @location.data
39
+ flunk("Should have raised an exception.")
40
+ rescue Rubuild::Env::Location::Error::DataEmpty => e
41
+ assert_same(e.location, @location)
42
+ end
43
+ end
44
+
45
+ def test_locationTwice
46
+ @location.set_data(:hello)
47
+ begin
48
+ @location.set_data(:goodbye)
49
+ flunk("Should have raised an exception.")
50
+ rescue Rubuild::Env::Location::Error::SetData::Already => e
51
+ assert_same(e.location, @location)
52
+ assert_same(e.newdata, :goodbye)
53
+ assert_same(@location.data, :hello)
54
+ end
55
+ end
56
+
57
+ def test_normal
58
+ block = proc do |dep|
59
+ @location.set_data(:hello)
60
+ end
61
+ bctx = @depfactory.create_context
62
+ dep = @depfactory.create_dep(block, "dep")
63
+ @location.found_dep.add_parent(dep)
64
+ @location.found_dep.load(bctx)
65
+ bctx.run
66
+ assert_same(@location.data, :hello)
67
+ end
68
+ end