rubywbem 0.1.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/AUTHORS +1 -0
- data/CHANGELOG +3 -0
- data/LICENSE +339 -0
- data/README +28 -0
- data/Rakefile +146 -0
- data/lib/wbem.rb +23 -0
- data/lib/wbem/cim_constants.rb +50 -0
- data/lib/wbem/cim_http.rb +137 -0
- data/lib/wbem/cim_obj.rb +1148 -0
- data/lib/wbem/cim_operations.rb +571 -0
- data/lib/wbem/cim_types.rb +195 -0
- data/lib/wbem/cim_xml.rb +1428 -0
- data/lib/wbem/tupleparse.rb +1181 -0
- data/lib/wbem/tupletree.rb +138 -0
- data/ruby-wbem.spec +54 -0
- data/testsuite/CIM_DTD_V22.dtd +324 -0
- data/testsuite/comfychair.rb +442 -0
- data/testsuite/runtests.sh +56 -0
- data/testsuite/test_cim_obj.rb +1610 -0
- data/testsuite/test_cim_operations.rb +702 -0
- data/testsuite/test_cim_xml.rb +1495 -0
- data/testsuite/test_nocasehash.rb +248 -0
- data/testsuite/test_tupleparse.rb +208 -0
- data/testsuite/validate.rb +93 -0
- metadata +68 -0
@@ -0,0 +1,442 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2006, Red Hat, Inc
|
3
|
+
# Scott Seago <sseago@redhat.com>
|
4
|
+
#
|
5
|
+
# derived from pywbem, written by Tim Potter <tpot@hp.com>, Martin Pool <mbp@hp.com>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation; either version 2 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# You should have received a copy of the GNU General Public License
|
13
|
+
# along with this program; if not, write to the Free Software
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
15
|
+
#
|
16
|
+
|
17
|
+
require "getoptlong"
|
18
|
+
require "fileutils"
|
19
|
+
|
20
|
+
COMFYCHAIRDOC = <<END
|
21
|
+
comfychair: a Ruby-based instrument of software torture.
|
22
|
+
(based on the Python version)
|
23
|
+
|
24
|
+
This is a test framework designed for testing programs written in
|
25
|
+
Ruby, or (through a fork/exec interface) any other language.
|
26
|
+
|
27
|
+
For more information, see the file README.comfychair.
|
28
|
+
|
29
|
+
To run a test suite based on ComfyChair, just run it as a program.
|
30
|
+
END
|
31
|
+
|
32
|
+
|
33
|
+
module Comfychair
|
34
|
+
|
35
|
+
class TestCase
|
36
|
+
#"""A base class for tests. This class defines required functions which
|
37
|
+
#can optionally be overridden by subclasses. It also provides some
|
38
|
+
#utility functions for"""
|
39
|
+
|
40
|
+
|
41
|
+
attr_reader :test_log, :_cleanups, :basedir, :rundir, :tmpdir
|
42
|
+
attr_writer :test_log, :_cleanups, :basedir, :rundir, :tmpdir
|
43
|
+
def initialize
|
44
|
+
@test_log = ""
|
45
|
+
@background_pids = []
|
46
|
+
@_cleanups = []
|
47
|
+
_enter_rundir()
|
48
|
+
_save_environment()
|
49
|
+
add_cleanup(:teardown)
|
50
|
+
end
|
51
|
+
|
52
|
+
# --------------------------------------------------
|
53
|
+
# Save and restore directory
|
54
|
+
def _enter_rundir
|
55
|
+
@basedir = Dir.getwd
|
56
|
+
self.add_cleanup(:_restore_directory)
|
57
|
+
@rundir = File.join(self.basedir,
|
58
|
+
'testtmp',
|
59
|
+
self.class.name)
|
60
|
+
@tmpdir = File.join(@rundir, 'tmp')
|
61
|
+
system("rm -fr %s" % @rundir)
|
62
|
+
FileUtils.mkdir_p(@tmpdir)
|
63
|
+
system("mkdir -p %s" % @rundir)
|
64
|
+
Dir.chdir(@rundir)
|
65
|
+
end
|
66
|
+
|
67
|
+
def _restore_directory
|
68
|
+
Dir.chdir(@basedir)
|
69
|
+
end
|
70
|
+
|
71
|
+
# --------------------------------------------------
|
72
|
+
# Save and restore environment
|
73
|
+
def _save_environment
|
74
|
+
@_saved_environ = ENV.to_hash
|
75
|
+
#ENV.each do |key, val|
|
76
|
+
# @_saved_environ[key] = val
|
77
|
+
#end
|
78
|
+
add_cleanup(:_restore_environment)
|
79
|
+
end
|
80
|
+
|
81
|
+
def _restore_environment
|
82
|
+
ENV.clear()
|
83
|
+
ENV.update(@_saved_environ)
|
84
|
+
end
|
85
|
+
|
86
|
+
def setup
|
87
|
+
#"""Set up test fixture."""
|
88
|
+
end
|
89
|
+
|
90
|
+
def teardown
|
91
|
+
#"""Tear down test fixture."""
|
92
|
+
end
|
93
|
+
|
94
|
+
def runtest
|
95
|
+
#"""Run the test."""
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_cleanup(methodname, obj = self)
|
99
|
+
#"""Queue a cleanup to be run when the test is complete."""
|
100
|
+
@_cleanups << obj.method(methodname)
|
101
|
+
end
|
102
|
+
|
103
|
+
def fail(reason = "")
|
104
|
+
#"""Say the test failed."""
|
105
|
+
raise AssertionError, reason
|
106
|
+
end
|
107
|
+
|
108
|
+
#############################################################
|
109
|
+
# Requisition methods
|
110
|
+
|
111
|
+
def require( predicate, message)
|
112
|
+
#"""Check a predicate for running this test.
|
113
|
+
|
114
|
+
#If the predicate value is not true, the test is skipped with a message explaining
|
115
|
+
#why."""
|
116
|
+
raise NotRunError, message unless predicate
|
117
|
+
end
|
118
|
+
|
119
|
+
def require_root
|
120
|
+
#"""Skip this test unless run by root."""
|
121
|
+
self.require(Process.uid == 0, "must be root to run this test")
|
122
|
+
end
|
123
|
+
|
124
|
+
#############################################################
|
125
|
+
# Assertion methods
|
126
|
+
|
127
|
+
def assert_(expr, reason = "")
|
128
|
+
raise AssertionError, reason unless expr
|
129
|
+
end
|
130
|
+
|
131
|
+
def assert_equal(a, b)
|
132
|
+
raise AssertionError, "assertEquals failed: %s, %s" % [a, b] unless (a == b)
|
133
|
+
end
|
134
|
+
|
135
|
+
def assert_notequal(a, b)
|
136
|
+
raise AssertionError, "assertNotEqual failed: %s, %s" % [a, b] if (a == b)
|
137
|
+
end
|
138
|
+
|
139
|
+
def assert_re_match(pattern, s)
|
140
|
+
#"""Assert that a string *contains* a particular pattern
|
141
|
+
|
142
|
+
#Inputs:
|
143
|
+
#pattern string: regular expression
|
144
|
+
#s string: to be searched
|
145
|
+
|
146
|
+
#Raises:
|
147
|
+
#AssertionError if not matched
|
148
|
+
#"""
|
149
|
+
unless Regexp.new(pattern).match(s)
|
150
|
+
raise AssertionError, "string does not contain regexp\n string: %s\n re: %s" % [s, pattern]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def assert_no_file(filename)
|
155
|
+
if File.exists?(filename)
|
156
|
+
raise AssertionError, "file exists but should not: %s" % filename
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
#############################################################
|
161
|
+
# Methods for running programs
|
162
|
+
|
163
|
+
def runcmd_background(cmd)
|
164
|
+
self.test_log = self.test_log + "Run in background:\n#{cmd}\n"
|
165
|
+
pid = fork()
|
166
|
+
if pid.nil?
|
167
|
+
# child
|
168
|
+
begin
|
169
|
+
exec("/bin/sh", "-c", cmd)
|
170
|
+
ensure
|
171
|
+
exit!(127)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
self.test_log = self.test_log + "pid: %d\n" % pid
|
175
|
+
return pid
|
176
|
+
end
|
177
|
+
|
178
|
+
def runcmd(cmd, expectedResult = 0)
|
179
|
+
#"""Run a command, fail if the command returns an unexpected exit
|
180
|
+
#code. Return the output produced."""
|
181
|
+
rc, output, stderr = self.runcmd_unchecked(cmd)
|
182
|
+
unless rc == expectedResult
|
183
|
+
raise AssertionError, "command returned %d; expected %s: \"%s\"\nstdout:\n%s\nstderr:\n%s""" % [rc, expectedResult, cmd, output, stderr]
|
184
|
+
end
|
185
|
+
return output, stderr
|
186
|
+
end
|
187
|
+
|
188
|
+
def run_captured(cmd)
|
189
|
+
#"""Run a command, capturing stdout and stderr.
|
190
|
+
#
|
191
|
+
#Based in part on popen2.py
|
192
|
+
#
|
193
|
+
#Returns (waitstatus, stdout, stderr)."""
|
194
|
+
pid = fork()
|
195
|
+
if pid.nil?
|
196
|
+
# child
|
197
|
+
begin
|
198
|
+
pid = Process.pid
|
199
|
+
openmode = FILE::O_WRONLY|FILE::O_CREAT|FILE::O_TRUNC
|
200
|
+
|
201
|
+
outfd = File.open('%d.out' % pid, openmode, 0666)
|
202
|
+
$stdout.reopen(outfd)
|
203
|
+
|
204
|
+
errfd = File.open('%d.err' % pid, openmode, 0666)
|
205
|
+
$stderr.reopen(errfd)
|
206
|
+
|
207
|
+
if cmd.is_a?(String)
|
208
|
+
cmd = ['/bin/sh', '-c', cmd]
|
209
|
+
end
|
210
|
+
exec(*cmd)
|
211
|
+
ensure
|
212
|
+
exit!(127)
|
213
|
+
end
|
214
|
+
else
|
215
|
+
# parent
|
216
|
+
exited_pid, waitstatus = Process.waitpid2(pid, 0)
|
217
|
+
stdout = File.open('%d.out' % pid)
|
218
|
+
stderr = File.open('%d.err' % pid)
|
219
|
+
return waitstatus, stdout, stderr
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def runcmd_unchecked(cmd, skip_on_noexec = 0)
|
225
|
+
#"""Invoke a command; return (exitcode, stdout, stderr)"""
|
226
|
+
waitstatus, stdout, stderr = self.run_captured(cmd)
|
227
|
+
if waitstatus.signaled?
|
228
|
+
raise AssertionError, "%s terminated with signal %d" % [cmd, os.waitstatus.termsig]
|
229
|
+
end
|
230
|
+
rc = waitstatus.exitstatus
|
231
|
+
self.test_log = self.test_log + "Run command: %s\nWait status: %#x (exit code %d, signal %d)\nstdout:\n%s\nstderr:\n%s" % [cmd, waitstatus, waitstatus, waitstatus.termsig, stdout, stderr]
|
232
|
+
if skip_on_noexec and rc == 127
|
233
|
+
# Either we could not execute the command or the command
|
234
|
+
# returned exit code 127. According to system(3) we can't
|
235
|
+
# tell the difference.
|
236
|
+
raise NotRunError, "could not execute %s" % cmd
|
237
|
+
end
|
238
|
+
return rc, stdout, stderr
|
239
|
+
end
|
240
|
+
|
241
|
+
def explain_failure(exc_info = nil)
|
242
|
+
print "test_log:\n"
|
243
|
+
print test_log, "\n"
|
244
|
+
end
|
245
|
+
|
246
|
+
def log(msg)
|
247
|
+
#"""Log a message to the test log. This message is displayed if
|
248
|
+
#the test fails, or when the runtests function is invoked with
|
249
|
+
#the verbose option."""
|
250
|
+
self.test_log = self.test_log + msg + "\n" unless msg.nil?
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class AssertionError < Exception; end
|
255
|
+
class NotRunError < Exception
|
256
|
+
#"""Raised if a test must be skipped because of missing resources"""
|
257
|
+
attr :value
|
258
|
+
def initialize(value = nil)
|
259
|
+
@value = value
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def Comfychair._report_error(testcase, ex, debugger)
|
264
|
+
#"""Ask the test case to explain failure, and optionally run a debugger
|
265
|
+
|
266
|
+
#Input:
|
267
|
+
#testcase TestCase instance
|
268
|
+
#debugger if true, a debugger function to be applied to the traceback
|
269
|
+
#"""
|
270
|
+
print "-----------------------------------------------------------------\n"
|
271
|
+
unless ex.nil?
|
272
|
+
print ex, "\n"
|
273
|
+
ex.backtrace.each do |line|
|
274
|
+
print line, "\n"
|
275
|
+
end
|
276
|
+
testcase.explain_failure()
|
277
|
+
print "-----------------------------------------------------------------\n"
|
278
|
+
end
|
279
|
+
if debugger
|
280
|
+
#tb = ex[2]
|
281
|
+
#debugger(tb)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def Comfychair.runtests(test_list, verbose = false, debugger = nil, quiet = false)
|
286
|
+
# """Run a series of tests.
|
287
|
+
|
288
|
+
# Inputs:
|
289
|
+
# test_list sequence of TestCase classes
|
290
|
+
# verbose print more information as testing proceeds
|
291
|
+
# debugger debugger object to be applied to errors
|
292
|
+
|
293
|
+
# Returns:
|
294
|
+
# unix return code: 0 for success, 1 for failures, 2 for test failure
|
295
|
+
# """
|
296
|
+
ret = 0
|
297
|
+
test_list.each do |test_class|
|
298
|
+
print "%-30s" % Comfychair._test_name(test_class)
|
299
|
+
# flush now so that long running tests are easier to follow
|
300
|
+
STDOUT.flush
|
301
|
+
|
302
|
+
obj = nil
|
303
|
+
begin
|
304
|
+
begin # run test and show result
|
305
|
+
obj = test_class.new
|
306
|
+
obj.setup()
|
307
|
+
obj.runtest()
|
308
|
+
print "OK\n"
|
309
|
+
# rescue KeyboardInterrupt => ex
|
310
|
+
# print "INTERRUPT\n"
|
311
|
+
# Comfychair._report_error(obj, ex, debugger) unless quiet
|
312
|
+
# ret = 2
|
313
|
+
# break
|
314
|
+
rescue NotRunError => msg
|
315
|
+
print "NOTRUN, %s\n" % msg.value
|
316
|
+
rescue Exception => ex
|
317
|
+
print "FAIL\n"
|
318
|
+
Comfychair._report_error(obj, ex, debugger) unless quiet
|
319
|
+
ret = 1
|
320
|
+
end
|
321
|
+
ensure
|
322
|
+
while obj and !obj._cleanups.empty?
|
323
|
+
begin
|
324
|
+
obj._cleanups.pop().call
|
325
|
+
# rescue KeyboardInterrupt => ex
|
326
|
+
# print "interrupted during teardown\n"
|
327
|
+
# Comfychair._report_error(obj, ex, debugger)
|
328
|
+
# ret = 2
|
329
|
+
# break
|
330
|
+
rescue => ex
|
331
|
+
print "error during teardown\n"
|
332
|
+
Comfychair._report_error(obj, ex, debugger) unless quiet
|
333
|
+
ret = 1
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
# Display log file if we're verbose
|
338
|
+
obj.explain_failure() if ret == 0 and verbose
|
339
|
+
end
|
340
|
+
return ret
|
341
|
+
end
|
342
|
+
|
343
|
+
def Comfychair._test_name(test_class)
|
344
|
+
#"""Return a human-readable name for a test class.
|
345
|
+
#"""
|
346
|
+
begin
|
347
|
+
return test_class.name
|
348
|
+
rescue
|
349
|
+
return test_class
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def Comfychair.print_help()
|
354
|
+
#"""Help for people running tests"""
|
355
|
+
msg = <<END
|
356
|
+
: software test suite based on ComfyChair
|
357
|
+
|
358
|
+
usage:
|
359
|
+
To run all tests, just run this program. To run particular tests,
|
360
|
+
list them on the command line.
|
361
|
+
|
362
|
+
options:
|
363
|
+
--help show usage message
|
364
|
+
--list list available tests
|
365
|
+
--verbose, -v show more information while running tests
|
366
|
+
END
|
367
|
+
# --post-mortem, -p enter Python debugger on error
|
368
|
+
print $0, msg
|
369
|
+
end
|
370
|
+
|
371
|
+
def Comfychair.print_list(test_list)
|
372
|
+
#"""Show list of available tests"""
|
373
|
+
test_list.each do |test_class|
|
374
|
+
print " %s\n" % Comfychair._test_name(test_class)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
def Comfychair.main(tests, extra_tests=[])
|
379
|
+
# """Main entry point for test suites based on ComfyChair.
|
380
|
+
|
381
|
+
# inputs:
|
382
|
+
# tests Sequence of TestCase subclasses to be run by default.
|
383
|
+
# extra_tests Sequence of TestCase subclasses that are available but
|
384
|
+
# not run by default.
|
385
|
+
|
386
|
+
# Test suites should contain this boilerplate:
|
387
|
+
|
388
|
+
# if __FILE__ == $0
|
389
|
+
# Comfychair.main(tests)
|
390
|
+
|
391
|
+
# This function handles standard options such as --help and --list, and
|
392
|
+
# by default runs all tests in the suggested order.
|
393
|
+
|
394
|
+
# Calls sys.exit() on completion.
|
395
|
+
#"""
|
396
|
+
opt_verbose = false
|
397
|
+
opt_quiet = false
|
398
|
+
debugger = nil
|
399
|
+
|
400
|
+
opts = GetoptLong.new(
|
401
|
+
[ '--help', GetoptLong::NO_ARGUMENT ],
|
402
|
+
[ '--list', GetoptLong::NO_ARGUMENT ],
|
403
|
+
[ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
|
404
|
+
[ '--post-mortem', '-p', GetoptLong::NO_ARGUMENT ],
|
405
|
+
[ '--quiet', '-q', GetoptLong::NO_ARGUMENT ])
|
406
|
+
|
407
|
+
opts.each do |opt, opt_arg|
|
408
|
+
case opt
|
409
|
+
when '--help'
|
410
|
+
Comfychair.print_help()
|
411
|
+
return
|
412
|
+
when '--list'
|
413
|
+
Comfychair.print_list(tests + extra_tests)
|
414
|
+
return
|
415
|
+
when '--verbose'
|
416
|
+
opt_verbose = true
|
417
|
+
when '--post-mortem'
|
418
|
+
# anything similar for ruby?
|
419
|
+
#import pdb
|
420
|
+
#debugger = pdb.post_mortem
|
421
|
+
raise ArgumentError, "--post-mortem not supported for Ruby"
|
422
|
+
when '--quiet'
|
423
|
+
opt_quiet = true unless opt_verbose
|
424
|
+
end
|
425
|
+
end
|
426
|
+
unless ARGV.empty?
|
427
|
+
all_tests = tests + extra_tests
|
428
|
+
by_name = {}
|
429
|
+
all_tests.each { |t| by_name[Comfychair._test_name(t)] = t}
|
430
|
+
which_tests = []
|
431
|
+
ARGV.each { |name| which_tests << by_name[name]}
|
432
|
+
else
|
433
|
+
which_tests = tests
|
434
|
+
end
|
435
|
+
|
436
|
+
exit(Comfychair.runtests(which_tests, opt_verbose, debugger, opt_quiet))
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
if __FILE__ == $0
|
441
|
+
print COMFYCHAIRDOC, "\n"
|
442
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# Parse command line
|
4
|
+
|
5
|
+
usage() {
|
6
|
+
echo "Usage: runtests.sh [-p RUBY] [-- ARGS]"
|
7
|
+
echo ""
|
8
|
+
echo "Where RUBY is the ruby binary to use (default 'ruby')"
|
9
|
+
echo "and ARGS are passed as command line parameters to the test"
|
10
|
+
echo "scripts. (The '--' must separate runtest parameters from"
|
11
|
+
echo "test script parameters)."
|
12
|
+
}
|
13
|
+
|
14
|
+
RUBY="ruby"
|
15
|
+
|
16
|
+
while getopts "p:" options; do
|
17
|
+
case $options in
|
18
|
+
p) RUBY=$OPTARG
|
19
|
+
;;
|
20
|
+
?) usage
|
21
|
+
exit 1
|
22
|
+
;;
|
23
|
+
esac
|
24
|
+
done
|
25
|
+
|
26
|
+
shift `expr $OPTIND - 1`
|
27
|
+
|
28
|
+
if [ "$1" = "all" ]; then
|
29
|
+
RUBY="ruby"
|
30
|
+
fi
|
31
|
+
|
32
|
+
# Run tests
|
33
|
+
|
34
|
+
failed=0
|
35
|
+
|
36
|
+
for test in test_*.rb; do
|
37
|
+
for ruby in $RUBY; do
|
38
|
+
echo ====================
|
39
|
+
echo $ruby $test
|
40
|
+
echo ====================
|
41
|
+
$ruby $test "$@"
|
42
|
+
if [ $? != 0 ]; then
|
43
|
+
failed=1
|
44
|
+
break
|
45
|
+
fi
|
46
|
+
done
|
47
|
+
done
|
48
|
+
|
49
|
+
# Display a message and set exit code appropriately
|
50
|
+
|
51
|
+
if [ $failed = 1 ]; then
|
52
|
+
echo TESTS FAILED
|
53
|
+
exit $failed
|
54
|
+
fi
|
55
|
+
|
56
|
+
echo TESTS PASSED
|