minilab 1.0.0-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/.document +2 -0
  2. data/CHANGES +2 -0
  3. data/LICENSE +19 -0
  4. data/README +107 -0
  5. data/Rakefile +145 -0
  6. data/config/environment.rb +15 -0
  7. data/config/objects.yml +22 -0
  8. data/lib/analog_io.rb +30 -0
  9. data/lib/digital_auxport_io.rb +49 -0
  10. data/lib/digital_configuration.rb +66 -0
  11. data/lib/digital_port_io.rb +68 -0
  12. data/lib/extension/extconf.rb +4 -0
  13. data/lib/extension/minilab_hardware.c +235 -0
  14. data/lib/extension/minilab_hardware.so +0 -0
  15. data/lib/library_translator.rb +48 -0
  16. data/lib/minilab.rb +149 -0
  17. data/lib/minilab_context.rb +39 -0
  18. data/lib/result_verifier.rb +14 -0
  19. data/test/integration/analog_input_output_test.rb +43 -0
  20. data/test/integration/connect_to_hardware_test.rb +13 -0
  21. data/test/integration/digital_input_output_test.rb +114 -0
  22. data/test/integration/integration_test.rb +53 -0
  23. data/test/integration/require_minilab_test.rb +9 -0
  24. data/test/system/analog_input.test +3 -0
  25. data/test/system/analog_output.test +37 -0
  26. data/test/system/digital_port_input.test +5 -0
  27. data/test/system/digital_port_output.test +39 -0
  28. data/test/system/digital_port_read_byte.test +26 -0
  29. data/test/system/digital_screw_terminals_input.test +2 -0
  30. data/test/system/digital_screw_terminals_output.test +11 -0
  31. data/test/system/minilab_driver.rb +85 -0
  32. data/test/test_helper.rb +11 -0
  33. data/test/unit/analog_io_test.rb +87 -0
  34. data/test/unit/digital_auxport_io_test.rb +114 -0
  35. data/test/unit/digital_configuration_test.rb +136 -0
  36. data/test/unit/digital_port_io_test.rb +117 -0
  37. data/test/unit/library_translator_test.rb +100 -0
  38. data/test/unit/minilab_context_test.rb +82 -0
  39. data/test/unit/minilab_hardware_test.rb +83 -0
  40. data/test/unit/minilab_test.rb +131 -0
  41. data/test/unit/result_verifier_test.rb +33 -0
  42. data/vendor/behaviors/lib/behaviors.rb +50 -0
  43. data/vendor/behaviors/tasks/behaviors_tasks.rake +140 -0
  44. data/vendor/behaviors/test/behaviors_tasks_test.rb +71 -0
  45. data/vendor/behaviors/test/behaviors_test.rb +50 -0
  46. data/vendor/behaviors/test/tasks_test/Rakefile +16 -0
  47. data/vendor/behaviors/test/tasks_test/doc/behaviors.html +55 -0
  48. data/vendor/behaviors/test/tasks_test/lib/user.rb +2 -0
  49. data/vendor/behaviors/test/tasks_test/test/user_test.rb +17 -0
  50. data/vendor/constructor/Rakefile +44 -0
  51. data/vendor/constructor/config/environment.rb +12 -0
  52. data/vendor/constructor/lib/constructor.rb +132 -0
  53. data/vendor/constructor/test/constructor_test.rb +366 -0
  54. data/vendor/constructor/test/helper.rb +3 -0
  55. data/vendor/diy/README +26 -0
  56. data/vendor/diy/Rakefile +18 -0
  57. data/vendor/diy/lib/constructor.rb +114 -0
  58. data/vendor/diy/lib/diy.rb +329 -0
  59. data/vendor/diy/proto/context.rb +117 -0
  60. data/vendor/diy/proto/context.yml +20 -0
  61. data/vendor/diy/test/diy_test.rb +370 -0
  62. data/vendor/diy/test/files/broken_construction.yml +7 -0
  63. data/vendor/diy/test/files/cat/cat.rb +4 -0
  64. data/vendor/diy/test/files/cat/extra_conflict.yml +5 -0
  65. data/vendor/diy/test/files/cat/heritage.rb +2 -0
  66. data/vendor/diy/test/files/cat/needs_input.yml +3 -0
  67. data/vendor/diy/test/files/cat/the_cat_lineage.rb +1 -0
  68. data/vendor/diy/test/files/dog/dog_model.rb +4 -0
  69. data/vendor/diy/test/files/dog/dog_presenter.rb +4 -0
  70. data/vendor/diy/test/files/dog/dog_view.rb +2 -0
  71. data/vendor/diy/test/files/dog/file_resolver.rb +2 -0
  72. data/vendor/diy/test/files/dog/other_thing.rb +2 -0
  73. data/vendor/diy/test/files/dog/simple.yml +11 -0
  74. data/vendor/diy/test/files/donkey/foo.rb +8 -0
  75. data/vendor/diy/test/files/donkey/foo/bar/qux.rb +7 -0
  76. data/vendor/diy/test/files/fud/objects.yml +13 -0
  77. data/vendor/diy/test/files/fud/toy.rb +15 -0
  78. data/vendor/diy/test/files/gnu/objects.yml +14 -0
  79. data/vendor/diy/test/files/gnu/thinger.rb +8 -0
  80. data/vendor/diy/test/files/goat/base.rb +8 -0
  81. data/vendor/diy/test/files/goat/can.rb +6 -0
  82. data/vendor/diy/test/files/goat/goat.rb +6 -0
  83. data/vendor/diy/test/files/goat/objects.yml +12 -0
  84. data/vendor/diy/test/files/goat/paper.rb +6 -0
  85. data/vendor/diy/test/files/goat/plane.rb +8 -0
  86. data/vendor/diy/test/files/goat/shirt.rb +6 -0
  87. data/vendor/diy/test/files/goat/wings.rb +8 -0
  88. data/vendor/diy/test/files/horse/holder_thing.rb +4 -0
  89. data/vendor/diy/test/files/horse/objects.yml +7 -0
  90. data/vendor/diy/test/files/yak/core_model.rb +4 -0
  91. data/vendor/diy/test/files/yak/core_presenter.rb +4 -0
  92. data/vendor/diy/test/files/yak/core_view.rb +1 -0
  93. data/vendor/diy/test/files/yak/data_source.rb +1 -0
  94. data/vendor/diy/test/files/yak/fringe_model.rb +4 -0
  95. data/vendor/diy/test/files/yak/fringe_presenter.rb +4 -0
  96. data/vendor/diy/test/files/yak/fringe_view.rb +1 -0
  97. data/vendor/diy/test/files/yak/my_objects.yml +21 -0
  98. data/vendor/diy/test/test_helper.rb +40 -0
  99. data/vendor/hardmock/CHANGES +8 -0
  100. data/vendor/hardmock/LICENSE +7 -0
  101. data/vendor/hardmock/README +48 -0
  102. data/vendor/hardmock/Rakefile +100 -0
  103. data/vendor/hardmock/TODO +7 -0
  104. data/vendor/hardmock/config/environment.rb +12 -0
  105. data/vendor/hardmock/homepage/demo.rb +21 -0
  106. data/vendor/hardmock/homepage/hardmock_sample.png +0 -0
  107. data/vendor/hardmock/homepage/index.html +65 -0
  108. data/vendor/hardmock/init.rb +3 -0
  109. data/vendor/hardmock/lib/hardmock.rb +634 -0
  110. data/vendor/hardmock/lib/method_cleanout.rb +14 -0
  111. data/vendor/hardmock/rcov.rake +18 -0
  112. data/vendor/hardmock/test/functional/assert_error_test.rb +52 -0
  113. data/vendor/hardmock/test/functional/auto_verify_test.rb +192 -0
  114. data/vendor/hardmock/test/functional/direct_mock_usage_test.rb +396 -0
  115. data/vendor/hardmock/test/functional/hardmock_test.rb +380 -0
  116. data/vendor/hardmock/test/test_helper.rb +23 -0
  117. data/vendor/hardmock/test/unit/expectation_builder_test.rb +18 -0
  118. data/vendor/hardmock/test/unit/expector_test.rb +56 -0
  119. data/vendor/hardmock/test/unit/method_cleanout_test.rb +35 -0
  120. data/vendor/hardmock/test/unit/mock_control_test.rb +172 -0
  121. data/vendor/hardmock/test/unit/mock_test.rb +273 -0
  122. data/vendor/hardmock/test/unit/simple_expectation_test.rb +345 -0
  123. data/vendor/hardmock/test/unit/trapper_test.rb +60 -0
  124. data/vendor/hardmock/test/unit/verify_error_test.rb +34 -0
  125. data/vendor/systir/systir.rb +403 -0
  126. data/vendor/systir/test/unit/ui/xml/testrunner.rb +192 -0
  127. data/vendor/systir/test/unit/ui/xml/xmltestrunner.xslt +109 -0
  128. metadata +235 -0
@@ -0,0 +1,329 @@
1
+ require 'yaml'
2
+
3
+ #
4
+ # DIY (Dependency Injection in Yaml) is a simple dependency injection library
5
+ # which focuses on declarative composition of objects through setter injection.
6
+ #
7
+ # == Examples
8
+ #
9
+ # === A Simple Context
10
+ #
11
+ # The context is a hash specified in in a yaml file. Each top-level key identifies
12
+ # an object. When the context is created and queried for an object, by default,
13
+ # the context will require a file with the same name:
14
+ # require 'foo'
15
+ # next, by default, it will call new on a class from the camel-cased name of the key:
16
+ # Foo.new
17
+ #
18
+ # foo.rb:
19
+ # class Foo; end
20
+ #
21
+ # context.yml:
22
+ # ---
23
+ # foo:
24
+ # bar:
25
+ #
26
+ # c = DIY::Context.from_file('context.yml')
27
+ # c[:foo] #=> #<Foo:0x81eb0>
28
+ #
29
+ # === Specifying Class Name
30
+ #
31
+ # If the class name isn't the camel-cased key:
32
+ #
33
+ # foo.rb:
34
+ # class MyFoo; end
35
+ #
36
+ # context.yml:
37
+ # ---
38
+ # foo:
39
+ # class: MyFoo
40
+ # bar:
41
+ #
42
+ # === Specifying Ruby File to Require
43
+ #
44
+ # If the file the class resides in isn't named after they key:
45
+ #
46
+ # fun_stuff.rb:
47
+ # class Foo; end
48
+ #
49
+ # context.yml:
50
+ # ---
51
+ # foo:
52
+ # lib: fun_stuff
53
+ # bar:
54
+ #
55
+ # === Constructor Arguments
56
+ #
57
+ # DIY allows specification of constructor arguments as hash key-value pairs
58
+ # using the <tt>compose</tt> directive.
59
+ #
60
+ # foo.rb:
61
+ # class Foo
62
+ # def initialize(args)
63
+ # @bar = args[:bar]
64
+ # @other = args[:other]
65
+ # end
66
+ # end
67
+ #
68
+ # context.yml:
69
+ # ---
70
+ # foo:
71
+ # compose: bar, other
72
+ # bar:
73
+ # other:
74
+ #
75
+ # To make constructor definition easier use constructor:
76
+ #
77
+ # foo.rb:
78
+ # class Foo
79
+ # constructor :bar, :other
80
+ # end
81
+ #
82
+ # If the constructor argument names don't match up with the object keys
83
+ # in the context, they can be mapped explicitly.
84
+ #
85
+ # foo.rb:
86
+ # class Foo
87
+ # constructor :bar, :other
88
+ # end
89
+ #
90
+ # context.yml:
91
+ # ---
92
+ # foo:
93
+ # bar: my_bar
94
+ # other: the_other_one
95
+ # my_bar:
96
+ # the_other_one:
97
+ #
98
+ module DIY
99
+ class Context
100
+ def initialize(context_hash, extra_inputs={})
101
+ raise "Nil context hash" unless context_hash
102
+ raise "Need a hash" unless context_hash.kind_of?(Hash)
103
+ [ "[]", "keys" ].each do |mname|
104
+ unless extra_inputs.respond_to?(mname)
105
+ raise "Extra inputs must respond to hash-like [] operator and methods #keys and #each"
106
+ end
107
+ end
108
+
109
+ # store extra inputs
110
+ if extra_inputs.kind_of?(Hash)
111
+ @extra_inputs = {}
112
+ extra_inputs.each { |k,v| @extra_inputs[k.to_s] = v } # smooth out the names
113
+ else
114
+ @extra_inputs = extra_inputs
115
+ end
116
+
117
+ # Collect object and subcontext definitions
118
+ @defs = {}
119
+ @sub_context_defs = {}
120
+ context_hash.each do |name,info|
121
+ name = name.to_s
122
+ case name
123
+ when /^\+/
124
+ # subcontext
125
+ @sub_context_defs[name.gsub(/^\+/,'')] = info
126
+ else
127
+ # normal object def
128
+ if extra_inputs_has(name)
129
+ raise ConstructionError.new(name, "Object definition conflicts with parent context")
130
+ end
131
+ @defs[name] = ObjectDef.new(name,info)
132
+ end
133
+ end
134
+
135
+
136
+ # init the cache
137
+ @cache = {}
138
+ @cache['this_context'] = self
139
+ end
140
+
141
+ def self.from_yaml(io_or_string, extra_inputs={})
142
+ raise "nil input to YAML" unless io_or_string
143
+ Context.new(YAML.load(io_or_string), extra_inputs)
144
+ end
145
+
146
+ def self.from_file(fname, extra_inputs={})
147
+ raise "nil file name" unless fname
148
+ self.from_yaml(File.read(fname), extra_inputs)
149
+ end
150
+
151
+ def get_object(obj_name)
152
+ key = obj_name.to_s
153
+ obj = @cache[key]
154
+ unless obj
155
+ if extra_inputs_has(key)
156
+ obj = @extra_inputs[key]
157
+ end
158
+ end
159
+ unless obj
160
+ obj = construct_object(key)
161
+ @cache[key] = obj
162
+ end
163
+ obj
164
+ end
165
+ alias :[] :get_object
166
+
167
+ def set_object(obj_name,obj)
168
+ key = obj_name.to_s
169
+ raise "object '#{key}' already exists in context" if @cache.keys.include?(key)
170
+ @cache[key] = obj
171
+ end
172
+ alias :[]= :set_object
173
+
174
+ def keys
175
+ @defs.keys
176
+ end
177
+
178
+ # Instantiate and yield the named subcontext
179
+ def within(sub_context_name)
180
+ # Find the subcontext definitaion:
181
+ context_def = @sub_context_defs[sub_context_name.to_s]
182
+ raise "No sub-context named #{sub_context_name}" unless context_def
183
+ # Instantiate a new context using self as parent:
184
+ context = Context.new( context_def, self )
185
+
186
+ yield context
187
+ end
188
+
189
+ def contains_object(obj_name)
190
+ key = obj_name.to_s
191
+ @defs.keys.member?(key) or extra_inputs_has(key)
192
+ end
193
+
194
+ def build_everything
195
+ @defs.keys.each { |k| self[k] }
196
+ end
197
+ alias :build_all :build_everything
198
+ alias :preinstantiate_singletons :build_everything
199
+
200
+ private
201
+ def construct_object(key)
202
+ # Find the object definition
203
+ obj_def = @defs[key]
204
+ raise "No object definition for '#{key}'" unless obj_def
205
+
206
+ # If object def mentions a library, load it
207
+ require obj_def.library if obj_def.library
208
+
209
+ # Resolve all components for the object
210
+ arg_hash = {}
211
+ obj_def.components.each do |name,value|
212
+ case value
213
+ when Lookup
214
+ arg_hash[name.to_sym] = get_object(value.name)
215
+ when StringValue
216
+ arg_hash[name.to_sym] = value.literal_value
217
+ else
218
+ raise "Cannot cope with component definition '#{value.inspect}'"
219
+ end
220
+ end
221
+ # Get a reference to the class for the object
222
+ big_c = get_class_for_name_with_module_delimeters(obj_def.class_name)
223
+ # Make and return the instance
224
+ if arg_hash.keys.size > 0
225
+ return big_c.new(arg_hash)
226
+ else
227
+ return big_c.new
228
+ end
229
+ rescue Exception => oops
230
+ cerr = ConstructionError.new(key,oops)
231
+ cerr.set_backtrace(oops.backtrace)
232
+ raise cerr
233
+ end
234
+
235
+ def get_class_for_name_with_module_delimeters(class_name)
236
+ class_name.split(/::/).inject(Object) do |mod,const_name| mod.const_get(const_name) end
237
+ end
238
+
239
+ def extra_inputs_has(key)
240
+ if key.nil? or key.strip == ''
241
+ raise ArgumentError.new("Cannot lookup objects with nil keys")
242
+ end
243
+ @extra_inputs.keys.member?(key) or @extra_inputs.keys.member?(key.to_sym)
244
+ end
245
+ end
246
+
247
+ class Lookup #:nodoc:
248
+ attr_reader :name
249
+ def initialize(obj_name)
250
+ @name = obj_name
251
+ end
252
+ end
253
+
254
+ class ObjectDef #:nodoc:
255
+ attr_accessor :name, :class_name, :library, :components
256
+ def initialize(name,info=nil)
257
+ if info
258
+ info = info.clone
259
+ else
260
+ info = {}
261
+ end
262
+
263
+ @components = {}
264
+
265
+ # Object name
266
+ @name = name
267
+
268
+ # Class name
269
+ @class_name = info.delete 'class'
270
+ @class_name ||= info.delete 'type'
271
+ @class_name ||= camelize(@name)
272
+
273
+ # Library
274
+ @library = info.delete 'library'
275
+ @library ||= info.delete 'lib'
276
+ @library ||= underscore(@class_name)
277
+
278
+ # Auto-compose
279
+ compose = info.delete 'compose'
280
+ if compose
281
+ case compose
282
+ when Array
283
+ auto_names = compose.map { |x| x.to_s }
284
+ when String
285
+ auto_names = compose.split(',').map { |x| x.to_s.strip }
286
+ when Symbol
287
+ auto_names = [ compose.to_s ]
288
+ else
289
+ raise "Cannot auto compose object #{@name}, bad 'compose' format: #{compose.inspect}"
290
+ end
291
+ end
292
+ auto_names ||= []
293
+ auto_names.each do |cname|
294
+ @components[cname] = Lookup.new(cname)
295
+ end
296
+
297
+ # Remaining keys
298
+ info.each do |key,val|
299
+ @components[key.to_s] = Lookup.new(val.to_s)
300
+ end
301
+ end
302
+
303
+ private
304
+ # Ganked this from Inflector:
305
+ def camelize(lower_case_and_underscored_word)
306
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
307
+ end
308
+ # Ganked this from Inflector:
309
+ def underscore(camel_cased_word)
310
+ camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
311
+ end
312
+ end
313
+
314
+ # Exception raised when an object can't be created which is defined in the context.
315
+ class ConstructionError < RuntimeError
316
+ def initialize(object_name, cause=nil) #:nodoc:
317
+ object_name = object_name
318
+ cause = cause
319
+ m = "Failed to construct '#{object_name}'"
320
+ if cause
321
+ m << "\n ...caused by:\n >>> #{cause}"
322
+ end
323
+ super m
324
+ end
325
+ end
326
+ end
327
+
328
+
329
+
@@ -0,0 +1,117 @@
1
+ require 'rubygems'
2
+ require 'active_support/inflector'
3
+ require 'yaml'
4
+
5
+ class DiyContext
6
+ def initialize(context_hash)
7
+ @defs = {}
8
+ context_hash.each do |name,info|
9
+ @defs[name.to_s] = ObjectDef.new(name,info)
10
+ end
11
+ @cache = {}
12
+ end
13
+
14
+ def self.from_yaml(text)
15
+ DiyContext.new(YAML.load(text))
16
+ end
17
+
18
+ def self.from_file(fname)
19
+ self.from_yaml(File.read(fname))
20
+ end
21
+
22
+ def get_object(obj_name)
23
+ key = obj_name.to_s
24
+ obj = @cache[key]
25
+ unless obj
26
+ obj = construct_object(key)
27
+ @cache[key] = obj
28
+ end
29
+ obj
30
+ end
31
+
32
+ def contains_object(obj_name)
33
+ !@defs[obj_name].nil?
34
+ end
35
+
36
+ private
37
+ def construct_object(key)
38
+ # Find the object definition
39
+ obj_def = @defs[key]
40
+ raise "No object definition for '#{key}'"
41
+
42
+ # If object def mentions a library, load it
43
+ require obj_def.library if obj_def.library
44
+
45
+ # Resolve all components for the object
46
+ arg_hash = {}
47
+ obj_def.components.each do |name,value|
48
+ case value
49
+ when Lookup
50
+ arg_hash[name.to_sym] = get_object(value.name)
51
+ when StringValue
52
+ arg_hash[name.to_sym] = value.literal_value
53
+ else
54
+ raise "Cannot cope with component definition '#{value.inspect}'"
55
+ end
56
+ end
57
+ # Get a reference to the class for the object
58
+ big_c = self.class.const_get(obj_def.class_name)
59
+ # Make and return the instance
60
+ big_c.new(arg_hash)
61
+ end
62
+
63
+ class Lookup
64
+ attr_reader :name
65
+ def initialize(obj_name)
66
+ @name = @obj_name
67
+ end
68
+ end
69
+
70
+ class ObjectDef
71
+ attr_accessor :name, :class_name, :library, :components
72
+ def initialize(name,info={})
73
+ info ||= {}
74
+
75
+ @components = {}
76
+
77
+ # Object name
78
+ @name = name
79
+
80
+ # Class name
81
+ @class_name = info.delete 'class'
82
+ @class_name ||= info.delete 'type'
83
+ @class_name ||= Inflector.camelize(@name)
84
+
85
+ # Library
86
+ @library = info.delete 'library'
87
+ @library ||= info.delete 'lib'
88
+ @library ||= Inflector.underscore(@class_name)
89
+
90
+ # Auto-compose
91
+ compose = info.delete 'compose'
92
+ if compose
93
+ case compose
94
+ when Array
95
+ auto_names = compose.map { |x| x.to_s }
96
+ when String
97
+ auto_names = compose.split(',').map { |x| x.to_s }
98
+ when Symbol
99
+ auto_names = [ compose.to_s ]
100
+ else
101
+ raise "Cannot auto compose object #{@name}, bad 'compose' format: #{compose.inspect}"
102
+ end
103
+ end
104
+ auto_names ||= []
105
+ auto_names.each do |cname|
106
+ @components[cname] = Lookup.new(cname)
107
+ end
108
+
109
+ # Remaining keys
110
+ info.each do |key,val|
111
+ @components[key.to_s] = Lookup.new(val.to_s)
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+
@@ -0,0 +1,20 @@
1
+ app_form:
2
+ class: MainAppForm
3
+
4
+ file_resolver:
5
+ class: FileResolver
6
+ lib: tools/happy_stuff
7
+
8
+ bep_host_config:
9
+ ini_file: (value) config.ini
10
+ compose: file_resolver
11
+
12
+ basic_dialog_shower:
13
+ compose:
14
+ - open_file_dialog
15
+ - error_dialog
16
+
17
+ hoss:
18
+ my_shower: basic_dialog_shower
19
+
20
+ boss: