rubuild-core 0.0.3

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,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