soda 0.0.1
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/lib/FieldUtils.rb +102 -0
- data/lib/Soda.rb +2628 -0
- data/lib/SodaCSV.rb +88 -0
- data/lib/SodaFireFox.rb +118 -0
- data/lib/SodaLogReporter.rb +810 -0
- data/lib/SodaReportSummery.rb +470 -0
- data/lib/SodaReporter.rb +452 -0
- data/lib/SodaTestCheck.rb +347 -0
- data/lib/SodaUtils.rb +931 -0
- data/lib/SodaXML.rb +129 -0
- data/lib/fields/CheckBoxField.rb +87 -0
- data/lib/fields/FileField.rb +37 -0
- data/lib/fields/LiField.rb +40 -0
- data/lib/fields/RadioField.rb +44 -0
- data/lib/fields/SelectField.rb +59 -0
- data/lib/fields/SodaField.rb +363 -0
- data/lib/fields/TextField.rb +31 -0
- data/lib/soda.rb +2 -0
- data/lib/utils/sodalookups.rb +465 -0
- metadata +114 -0
data/lib/SodaReporter.rb
ADDED
@@ -0,0 +1,452 @@
|
|
1
|
+
###############################################################################
|
2
|
+
# Copyright (c) 2010, SugarCRM, Inc.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
# * Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer in the
|
11
|
+
# documentation and/or other materials provided with the distribution.
|
12
|
+
# * Neither the name of SugarCRM, Inc. nor the
|
13
|
+
# names of its contributors may be used to endorse or promote products
|
14
|
+
# derived from this software without specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL SugarCRM, Inc. BE LIABLE FOR ANY
|
20
|
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
22
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
23
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
###############################################################################
|
27
|
+
|
28
|
+
###############################################################################
|
29
|
+
# Required Ruby libs:
|
30
|
+
###############################################################################
|
31
|
+
require 'SodaUtils'
|
32
|
+
require 'tmpdir'
|
33
|
+
require 'SodaLogReporter'
|
34
|
+
|
35
|
+
###############################################################################
|
36
|
+
# SodaReporter -- Class
|
37
|
+
#
|
38
|
+
# Params:
|
39
|
+
# testfile: This is a soda XML test file.
|
40
|
+
# savehtml: This tells Soda to save html files that caused an issue.
|
41
|
+
# resultsdir: This is the directory where you want to store all results.
|
42
|
+
# debug: Setting this to true will cause this class to print full debug
|
43
|
+
# messages.
|
44
|
+
#
|
45
|
+
# simple reporter class that tracks asserts, exceptions, and log messages
|
46
|
+
###############################################################################
|
47
|
+
class SodaReporter
|
48
|
+
|
49
|
+
def initialize(testfile, savehtml = false, resultsdir = nil, debug = 0,
|
50
|
+
callback = nil, rerun = false)
|
51
|
+
@sodatest_file = testfile
|
52
|
+
@saveHtmlFiles = savehtml
|
53
|
+
@debug = debug
|
54
|
+
@js_error_count = 0
|
55
|
+
@css_error_count = 0
|
56
|
+
@asserts_count = 0
|
57
|
+
@exception_major_count = 0
|
58
|
+
@assertFails_count = 0
|
59
|
+
@exception_count = 0
|
60
|
+
@test_count = 0
|
61
|
+
@test_skip_count = 0
|
62
|
+
@fatals = 0
|
63
|
+
@total = 0
|
64
|
+
@failureCount = 0
|
65
|
+
@savedPages = 0
|
66
|
+
@ResultsDir = "#{Dir.pwd}"
|
67
|
+
@path = nil
|
68
|
+
@htmllog_filename = nil
|
69
|
+
@log_filename = nil
|
70
|
+
@print_callback = callback
|
71
|
+
hostname = "#{ENV['HOSTNAME']}"
|
72
|
+
|
73
|
+
if (resultsdir != nil)
|
74
|
+
@ResultsDir = resultsdir
|
75
|
+
end
|
76
|
+
|
77
|
+
if ( (hostname.empty?) || (hostname.length < 5) )
|
78
|
+
hostname = `hostname`
|
79
|
+
hostname = hostname.chomp()
|
80
|
+
end
|
81
|
+
|
82
|
+
SodaUtils.PrintSoda("Debugging: => #{debug}\n")
|
83
|
+
SodaUtils.PrintSoda("Soda Test File: => #{@sodatest_file}\n")
|
84
|
+
base_testfile_name = File.basename(@sodatest_file, '.xml')
|
85
|
+
|
86
|
+
if (rerun)
|
87
|
+
base_testfile_name << "-SodaRerun"
|
88
|
+
end
|
89
|
+
|
90
|
+
now = Time.now().strftime("%d-%m-%Y-%H-%M")
|
91
|
+
|
92
|
+
if (resultsdir == nil)
|
93
|
+
@ResultsDir = @ResultsDir + "/#{base_testfile_name}-#{now}-results"
|
94
|
+
end
|
95
|
+
|
96
|
+
FileUtils.mkdir_p(@ResultsDir)
|
97
|
+
|
98
|
+
@path = "#{@ResultsDir}/#{base_testfile_name}"
|
99
|
+
if (@path =~ /sugarinit/i)
|
100
|
+
@log_filename = "#{@path}-#{hostname}.tmp"
|
101
|
+
@htmllog_filename = "#{@ResultsDir}/Report-#{base_testfile_name}"+
|
102
|
+
"-#{hostname}.html"
|
103
|
+
else
|
104
|
+
@htmllog_filename = "#{@ResultsDir}/Report-#{base_testfile_name}.html"
|
105
|
+
@log_filename = "#{@path}.tmp"
|
106
|
+
end
|
107
|
+
|
108
|
+
@logfile = File.new(@log_filename, 'w+')
|
109
|
+
@logfile.sync = true # force buffers to write to disk asap! #
|
110
|
+
SodaUtils.PrintSoda("Created log file: => #{@log_filename}\n")
|
111
|
+
log("[New Test]\n")
|
112
|
+
log("Starting soda test: #{@sodatest_file}\n")
|
113
|
+
log("Saving HTML files => #{@saveHtmlFiles.to_s()}.\n")
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
###############################################################################
|
118
|
+
# IncSkippedTest -- Method
|
119
|
+
# This method incerments the count by 1 for tests that were skipped.
|
120
|
+
#
|
121
|
+
# Input:
|
122
|
+
# None.
|
123
|
+
#
|
124
|
+
# Output:
|
125
|
+
# None.
|
126
|
+
#
|
127
|
+
###############################################################################
|
128
|
+
def IncSkippedTest()
|
129
|
+
@test_skip_count += 1
|
130
|
+
end
|
131
|
+
public :IncSkippedTest
|
132
|
+
|
133
|
+
###############################################################################
|
134
|
+
# IncTestCount -- Method
|
135
|
+
# This method incerments the count by 1 for tests that were ran
|
136
|
+
#
|
137
|
+
# Input:
|
138
|
+
# None.
|
139
|
+
#
|
140
|
+
# Output:
|
141
|
+
# None.
|
142
|
+
#
|
143
|
+
###############################################################################
|
144
|
+
def IncTestCount()
|
145
|
+
@test_count += 1
|
146
|
+
end
|
147
|
+
public :IncTestCount
|
148
|
+
|
149
|
+
###############################################################################
|
150
|
+
# ReportHTML -- Method
|
151
|
+
# This function will generate an html report from the raw soda log file.
|
152
|
+
#
|
153
|
+
# Params:
|
154
|
+
# None.
|
155
|
+
#
|
156
|
+
# Results:
|
157
|
+
# None.
|
158
|
+
#
|
159
|
+
###############################################################################
|
160
|
+
def ReportHTML
|
161
|
+
slr = SodaLogReporter.new(@log_filename, @htmllog_filename)
|
162
|
+
slr.GenerateReport()
|
163
|
+
msg = "Created new html report: #{@htmllog_filename}\n"
|
164
|
+
SodaUtils.PrintSoda(msg)
|
165
|
+
|
166
|
+
if (@print_callback != nil)
|
167
|
+
@print_callback.call(msg)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
###############################################################################
|
172
|
+
# ReportFailure -- Method
|
173
|
+
# This function reports and counts general Soda failures.
|
174
|
+
#
|
175
|
+
# Params:
|
176
|
+
# msg: This is the string failure message to be reported.
|
177
|
+
#
|
178
|
+
# Results:
|
179
|
+
# None.
|
180
|
+
#
|
181
|
+
###############################################################################
|
182
|
+
def ReportFailure(msg)
|
183
|
+
@failureCount += 1
|
184
|
+
log("#{msg}", SodaUtils::ERROR)
|
185
|
+
end
|
186
|
+
|
187
|
+
###############################################################################
|
188
|
+
# ReportJavaScriptError -- Method
|
189
|
+
# This function reports and counts javascript failures.
|
190
|
+
#
|
191
|
+
# Params:
|
192
|
+
# msg: This is the string failure message to be reported.
|
193
|
+
# skipcssreport: This skipps reporting CSS errors.
|
194
|
+
#
|
195
|
+
# Results:
|
196
|
+
# Always returns 0.
|
197
|
+
#
|
198
|
+
###############################################################################
|
199
|
+
def ReportJavaScriptError(msg, skipcssreport = false)
|
200
|
+
|
201
|
+
if ( (msg =~ /Cat::CSS\s+Parser/i) && (skipcssreport != true) )
|
202
|
+
msg = msg.gsub(/javascript\s+error:/i, "Css Error:")
|
203
|
+
log("#{msg}", SodaUtils::WARN)
|
204
|
+
@css_error_count += 1
|
205
|
+
elsif ( (msg =~ /Cat::CSS\s+Parser/i) && (skipcssreport != false) )
|
206
|
+
@css_error_count += 1
|
207
|
+
return 0
|
208
|
+
else
|
209
|
+
log("#{msg}", SodaUtils::ERROR)
|
210
|
+
@js_error_count += 1
|
211
|
+
end
|
212
|
+
|
213
|
+
return 0
|
214
|
+
end
|
215
|
+
|
216
|
+
###############################################################################
|
217
|
+
# SavePage -- Method
|
218
|
+
# This method saves an given HTML page from the browser for later use.
|
219
|
+
#
|
220
|
+
# Params:
|
221
|
+
# reason: Just a string so when this methos is called the caller can
|
222
|
+
# give a reason in the log file. I'd hope this is used to report
|
223
|
+
# errors.
|
224
|
+
#
|
225
|
+
# Results:
|
226
|
+
# always returns 0.
|
227
|
+
#
|
228
|
+
###############################################################################
|
229
|
+
def SavePage(reason = "")
|
230
|
+
if (@saveHtmlFiles != true)
|
231
|
+
return 0
|
232
|
+
end
|
233
|
+
|
234
|
+
@savedPages += 1
|
235
|
+
save_file_name = "#{@path}page#{@savedPages}.html"
|
236
|
+
page = File.new(save_file_name, 'w+')
|
237
|
+
page.write($curSoda.browser.url + "\n<br>#{reason}\n<br>" +
|
238
|
+
$curSoda.browser.html)
|
239
|
+
page.close()
|
240
|
+
|
241
|
+
log("HTML Saved: #{save_file_name}\n")
|
242
|
+
|
243
|
+
return 0
|
244
|
+
end
|
245
|
+
|
246
|
+
###############################################################################
|
247
|
+
# AddEventCount -- Method
|
248
|
+
# This function incerments the internal event counter.
|
249
|
+
#
|
250
|
+
# Params:
|
251
|
+
# None.
|
252
|
+
#
|
253
|
+
# Results:
|
254
|
+
# None.
|
255
|
+
#
|
256
|
+
###############################################################################
|
257
|
+
def AddEventCount
|
258
|
+
@total += 1
|
259
|
+
end
|
260
|
+
|
261
|
+
###############################################################################
|
262
|
+
# EndTestReport -- Method
|
263
|
+
# This function is to be called after a test finishes running, so that the
|
264
|
+
# proper formatting is do to allow for an easy to parse raw log file.
|
265
|
+
#
|
266
|
+
# Params:
|
267
|
+
# None.
|
268
|
+
#
|
269
|
+
# Results:
|
270
|
+
# None.
|
271
|
+
#
|
272
|
+
###############################################################################
|
273
|
+
def EndTestReport
|
274
|
+
log("Soda test: #{@sodatest_file} finished.\n")
|
275
|
+
log("[End Test]\n")
|
276
|
+
@logfile.close()
|
277
|
+
|
278
|
+
tmp_logfile = File.dirname(@log_filename)
|
279
|
+
tmp_logfile += "/"
|
280
|
+
tmp_logfile += File.basename("#{@log_filename}", ".tmp")
|
281
|
+
tmp_logfile += ".log"
|
282
|
+
File.rename(@log_filename, tmp_logfile)
|
283
|
+
@log_filename = tmp_logfile
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
###############################################################################
|
288
|
+
# log -- Method
|
289
|
+
# This method will log soda message to both stdout & the report's log file.
|
290
|
+
#
|
291
|
+
# Params:
|
292
|
+
# msg: This is a string message to log.
|
293
|
+
#
|
294
|
+
# error: Default is false, setting to true will format the message as an
|
295
|
+
# error.
|
296
|
+
#
|
297
|
+
# Results:
|
298
|
+
# None.
|
299
|
+
#
|
300
|
+
###############################################################################
|
301
|
+
def log(msg, error = 0)
|
302
|
+
SodaUtils.PrintSoda(msg, error, @logfile, @debug)
|
303
|
+
SodaUtils.PrintSoda(msg, error, nil, @debug, 1, @print_callback)
|
304
|
+
end
|
305
|
+
|
306
|
+
###############################################################################
|
307
|
+
# ReportException -- Method
|
308
|
+
# This method reports an Soda Exceptions from the Soda class.
|
309
|
+
#
|
310
|
+
# Params:
|
311
|
+
# sodaException: This is the exception that is passed from Soda.
|
312
|
+
#
|
313
|
+
# mojor: Tells use if this was a mojor exception or now.
|
314
|
+
#
|
315
|
+
# file: The soda test file that the exception was raised by durring the
|
316
|
+
# test.
|
317
|
+
#
|
318
|
+
# Results:
|
319
|
+
# None.
|
320
|
+
#
|
321
|
+
# Notes:
|
322
|
+
# The major param seems totally useless and was left over from the org
|
323
|
+
# code from this file. Soda.rb only ever calls this method with major.
|
324
|
+
# So I will be killer this param soon...
|
325
|
+
#
|
326
|
+
###############################################################################
|
327
|
+
def ReportException(sodaException, major = false, file = false)
|
328
|
+
msg = nil
|
329
|
+
@exception_count += 1
|
330
|
+
|
331
|
+
if (sodaException.message.empty?)
|
332
|
+
msg = "No exception message found!"
|
333
|
+
else
|
334
|
+
msg = sodaException.message
|
335
|
+
end
|
336
|
+
|
337
|
+
if (file)
|
338
|
+
log("Exception raised for file: #{file}\n", SodaUtils::ERROR)
|
339
|
+
else
|
340
|
+
log("Exception raised: #{msg}\n", SodaUtils::ERROR)
|
341
|
+
end
|
342
|
+
|
343
|
+
if (major)
|
344
|
+
@exception_major_count += 1
|
345
|
+
bt = "--Exception Backtrace: " + sodaException.backtrace.join("--") +
|
346
|
+
"\n"
|
347
|
+
btm = "--Exception Message: #{msg}\n"
|
348
|
+
log("Major exception raised for file: #{file}" + btm + bt,
|
349
|
+
SodaUtils::ERROR)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
###############################################################################
|
354
|
+
# Assert -- Method
|
355
|
+
# This method assert that the exp is equal to TRUE, and reports the results
|
356
|
+
#
|
357
|
+
# Params:
|
358
|
+
# exp: The expression to evaulate.
|
359
|
+
# msg: The message to report about the assertion.
|
360
|
+
#
|
361
|
+
#
|
362
|
+
# Results:
|
363
|
+
# returns -1 on assert failed, or 0 on success.
|
364
|
+
#
|
365
|
+
###############################################################################
|
366
|
+
def Assert(exp, msg = "", file = "", line_number = "")
|
367
|
+
result = 0
|
368
|
+
@asserts_count += 1
|
369
|
+
url = nil
|
370
|
+
|
371
|
+
url = "#{$curSoda.browser.url}"
|
372
|
+
if ( (url.empty?) || (url.length < 1) || (url == "") )
|
373
|
+
url = "Unknown URL casued this Assert!"
|
374
|
+
end
|
375
|
+
|
376
|
+
if (file.empty?)
|
377
|
+
file = "No file provided."
|
378
|
+
end
|
379
|
+
|
380
|
+
if (msg.empty?)
|
381
|
+
msg = "No Assert message provided!"
|
382
|
+
end
|
383
|
+
|
384
|
+
if ( (line_number == nil) || (line_number.empty?))
|
385
|
+
line_number = "Unknown line number"
|
386
|
+
end
|
387
|
+
|
388
|
+
if (!exp)
|
389
|
+
ass_msg = "Assertion: Failed!:--#{url}--#{file}" +
|
390
|
+
"--Assertion Message: #{msg}--Line: #{line_number}"
|
391
|
+
ass_msg = ass_msg.sub(/\n/,"")
|
392
|
+
ass_msg << "\n"
|
393
|
+
|
394
|
+
log(ass_msg, 1)
|
395
|
+
SavePage(msg)
|
396
|
+
@assertFails_count += 1
|
397
|
+
result = -1
|
398
|
+
else
|
399
|
+
if (msg.empty?)
|
400
|
+
log("Assertion: Passed.\n")
|
401
|
+
else
|
402
|
+
log("Assertion: Passed: #{msg}.\n")
|
403
|
+
end
|
404
|
+
result = 0
|
405
|
+
end
|
406
|
+
|
407
|
+
return result
|
408
|
+
end
|
409
|
+
|
410
|
+
###############################################################################
|
411
|
+
# AssertNot -- Method
|
412
|
+
# This method asserts if the exp is equal to FALSE, and reports the results
|
413
|
+
#
|
414
|
+
# Params:
|
415
|
+
# exp: The expression to evaulate.
|
416
|
+
# msg: The message to report with the assert.
|
417
|
+
#
|
418
|
+
#
|
419
|
+
###############################################################################
|
420
|
+
def AssertNot(exp, msg = "", file = "")
|
421
|
+
Assert(!exp, msg, file)
|
422
|
+
end
|
423
|
+
|
424
|
+
###############################################################################
|
425
|
+
# SodaPrintCurrentReport -- Method
|
426
|
+
# This method is used for printing out the current results of the report.
|
427
|
+
#
|
428
|
+
# Params:
|
429
|
+
# None.
|
430
|
+
#
|
431
|
+
# Results:
|
432
|
+
# None.
|
433
|
+
#
|
434
|
+
###############################################################################
|
435
|
+
def SodaPrintCurrentReport()
|
436
|
+
msg = "Soda Test Report:" +
|
437
|
+
"--Test File:#{@sodatest_file}" +
|
438
|
+
"--Test Failure Count:#{@failureCount}" +
|
439
|
+
"--Test CSS Error Count:#{@css_error_count}" +
|
440
|
+
"--Test JavaScript Error Count:#{@js_error_count}" +
|
441
|
+
"--Test Assert Failures:#{@assertFails_count}" +
|
442
|
+
"--Test Event Count:#{@total}" +
|
443
|
+
"--Test Assert Count:#{@asserts_count}" +
|
444
|
+
"--Test Exceptions:#{@exception_count}" +
|
445
|
+
"--Test Major Exceptions: #{@exception_major_count}" +
|
446
|
+
"--Test Count:#{@test_count}" +
|
447
|
+
"--Test Skip Count:#{@test_skip_count}\n"
|
448
|
+
log(msg)
|
449
|
+
end
|
450
|
+
|
451
|
+
end
|
452
|
+
|
@@ -0,0 +1,347 @@
|
|
1
|
+
###############################################################################
|
2
|
+
# Copyright (c) 2010, SugarCRM, Inc.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
# * Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer in the
|
11
|
+
# documentation and/or other materials provided with the distribution.
|
12
|
+
# * Neither the name of SugarCRM, Inc. nor the
|
13
|
+
# names of its contributors may be used to endorse or promote products
|
14
|
+
# derived from this software without specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL SugarCRM, Inc. BE LIABLE FOR ANY
|
20
|
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
22
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
23
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
###############################################################################
|
27
|
+
|
28
|
+
###############################################################################
|
29
|
+
# Need Ruby Libs:
|
30
|
+
###############################################################################
|
31
|
+
require 'rubygems'
|
32
|
+
require 'getoptlong'
|
33
|
+
require 'digest/md5'
|
34
|
+
require 'libxml'
|
35
|
+
require 'SodaXML'
|
36
|
+
require 'SodaUtils'
|
37
|
+
|
38
|
+
###############################################################################
|
39
|
+
###############################################################################
|
40
|
+
class SodaTestCheck
|
41
|
+
|
42
|
+
def initialize(sodatest, reportobj)
|
43
|
+
err = 0
|
44
|
+
sodadata = nil
|
45
|
+
@SODA_ELEMENTS_FILE = "SodaElements.xml"
|
46
|
+
$ERROR_COUNT = 0
|
47
|
+
@report = reportobj
|
48
|
+
@sodatest = sodatest
|
49
|
+
end
|
50
|
+
|
51
|
+
###############################################################################
|
52
|
+
###############################################################################
|
53
|
+
def Check()
|
54
|
+
err = 0
|
55
|
+
elements_root = nil
|
56
|
+
elements_data = nil
|
57
|
+
sodadata = nil
|
58
|
+
msg = ""
|
59
|
+
|
60
|
+
if (!File.exist?(@SODA_ELEMENTS_FILE))
|
61
|
+
msg = "Error: can't find needed file: '#{@SODA_ELEMENTS_FILE}'!\n"
|
62
|
+
@report.ReportFailure(msg)
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
|
66
|
+
elements_root = ParseSodaElementsXML()
|
67
|
+
if (elements_root == nil)
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
|
71
|
+
elements_data = ElementsXMLToData(elements_root)
|
72
|
+
if (elements_data.empty?)
|
73
|
+
msg = "Error: XML element data is empty!\n"
|
74
|
+
@report.ReportFailure(msg)
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
|
78
|
+
err = CheckFileformat(@sodatest)
|
79
|
+
if (err != 0)
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
|
83
|
+
sodadata = ProcessSodaTestFile(@sodatest)
|
84
|
+
if (sodadata == nil)
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
|
88
|
+
return true
|
89
|
+
end
|
90
|
+
public :Check
|
91
|
+
|
92
|
+
###############################################################################
|
93
|
+
# ParseSodaElementsXML -- method
|
94
|
+
# This finction parses the SodaElements.xml file.
|
95
|
+
#
|
96
|
+
# Input:
|
97
|
+
# None.
|
98
|
+
#
|
99
|
+
# Output:
|
100
|
+
# returns the doc.root from the XML parser, or nil on error.
|
101
|
+
#
|
102
|
+
###############################################################################
|
103
|
+
def ParseSodaElementsXML()
|
104
|
+
parser = nil
|
105
|
+
doc = nil
|
106
|
+
kids = nil
|
107
|
+
|
108
|
+
begin
|
109
|
+
LibXML::XML.default_line_numbers = true
|
110
|
+
parser = LibXML::XML::Parser.file(@SODA_ELEMENTS_FILE)
|
111
|
+
doc = parser.parse()
|
112
|
+
rescue Exception => e
|
113
|
+
doc = nil
|
114
|
+
@report.ReportException(e, false, @sodatest)
|
115
|
+
ensure
|
116
|
+
end
|
117
|
+
|
118
|
+
return nil if (doc == nil)
|
119
|
+
return doc.root
|
120
|
+
end
|
121
|
+
###############################################################################
|
122
|
+
# ElementsXMLToData -- method
|
123
|
+
# This function generates a hash of the SodaElements.xml file.
|
124
|
+
#
|
125
|
+
# Input:
|
126
|
+
# node: this is the root node from the xml parser.
|
127
|
+
#
|
128
|
+
# Output:
|
129
|
+
# returns a hash of the xml node.
|
130
|
+
#
|
131
|
+
###############################################################################
|
132
|
+
def ElementsXMLToData(node)
|
133
|
+
elements = {}
|
134
|
+
kids = nil
|
135
|
+
|
136
|
+
if (!node.children?)
|
137
|
+
return {}
|
138
|
+
end
|
139
|
+
|
140
|
+
kids = node.children()
|
141
|
+
kids.each do |kid|
|
142
|
+
next if ( (kid.name == "text") || (!kid.children?) )
|
143
|
+
|
144
|
+
elements[kid.name] = Hash.new()
|
145
|
+
elements[kid.name]['accessor_attributes'] = []
|
146
|
+
elements[kid.name]['soda_attributes'] = []
|
147
|
+
|
148
|
+
elems = kid.children()
|
149
|
+
elems.each do |e|
|
150
|
+
case (e.name)
|
151
|
+
when "accessor_attributes"
|
152
|
+
access_kids = e.children()
|
153
|
+
access_kids.each do |access|
|
154
|
+
next if (access.name == "text")
|
155
|
+
elements[kid.name]["accessor_attributes"].push(access.content)
|
156
|
+
end
|
157
|
+
when "soda_attributes"
|
158
|
+
access_kids = e.children()
|
159
|
+
access_kids.each do |access|
|
160
|
+
next if (access.name == "text")
|
161
|
+
|
162
|
+
if (access.name =~ /accessor/)
|
163
|
+
elements[kid.name]["soda_attributes"].push(
|
164
|
+
access.content)
|
165
|
+
end
|
166
|
+
|
167
|
+
if (access.children?)
|
168
|
+
access_kids = access.children()
|
169
|
+
tmp_hash = {}
|
170
|
+
tmp_hash[access.name] = []
|
171
|
+
access_kids.each do |access_kid|
|
172
|
+
next if (access_kid.name == "text")
|
173
|
+
tmp_hash[access.name].push(access_kid.content)
|
174
|
+
end
|
175
|
+
elements[kid.name]["soda_attributes"].push(tmp_hash)
|
176
|
+
else
|
177
|
+
elements[kid.name]["soda_attributes"].push(
|
178
|
+
access.content)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
return elements
|
186
|
+
end
|
187
|
+
private :ElementsXMLToData
|
188
|
+
|
189
|
+
###############################################################################
|
190
|
+
# ProcessSodaTestFile -- method
|
191
|
+
# This function parses a soda test into an array of hashes, using the
|
192
|
+
# same SodaXML class that Soda uses, so there is a 1 to 1 on all data.
|
193
|
+
#
|
194
|
+
# Input:
|
195
|
+
# file: this is a soda test file.
|
196
|
+
#
|
197
|
+
# Output:
|
198
|
+
# returns an array of hashes, or nil on error.
|
199
|
+
#
|
200
|
+
###############################################################################
|
201
|
+
def ProcessSodaTestFile(file)
|
202
|
+
data = nil
|
203
|
+
|
204
|
+
begin
|
205
|
+
data = SodaXML.new.parse(file)
|
206
|
+
rescue Exception => e
|
207
|
+
@report.ReportException(e, false, @sodatest)
|
208
|
+
data = nil
|
209
|
+
ensure
|
210
|
+
end
|
211
|
+
|
212
|
+
return data
|
213
|
+
end
|
214
|
+
private :ProcessSodaTestFile
|
215
|
+
|
216
|
+
###############################################################################
|
217
|
+
# CheckTest -- function
|
218
|
+
# This function checks a soda test against the SodaElements.xml file to
|
219
|
+
# ensure that the tests is not using unsupported XML.
|
220
|
+
#
|
221
|
+
# Input:
|
222
|
+
# sodadata: This is an array of hashes from ProcessSodaTestFile().
|
223
|
+
# supported: This is the hash of the SodaElements.xml file.
|
224
|
+
#
|
225
|
+
# Results:
|
226
|
+
# None.
|
227
|
+
#
|
228
|
+
###############################################################################
|
229
|
+
def CheckTest(sodadata, supported)
|
230
|
+
|
231
|
+
sodadata.each do |test_hash|
|
232
|
+
if (!test_hash.key?('do'))
|
233
|
+
@report.ReportFailure("Failed to find expected test do "+
|
234
|
+
"element for test: #{file}, line: #{test_hash['line_number']}"+
|
235
|
+
"!\n")
|
236
|
+
next
|
237
|
+
end
|
238
|
+
|
239
|
+
test_element = test_hash['do']
|
240
|
+
next if (test_element == "comment")
|
241
|
+
test_hash.delete('do')
|
242
|
+
|
243
|
+
if (!supported.key?("#{test_element}"))
|
244
|
+
@report.ReportFailure("Failed to find a supported Soda"+
|
245
|
+
" element for: '#{test_element}', line: "+
|
246
|
+
"#{test_hash['line_number']}!\n")
|
247
|
+
$ERROR_COUNT += 1
|
248
|
+
next
|
249
|
+
end
|
250
|
+
|
251
|
+
if (test_hash.key?('children'))
|
252
|
+
result = CheckTest(test_hash['children'], supported)
|
253
|
+
test_hash.delete('children')
|
254
|
+
end
|
255
|
+
|
256
|
+
test_hash.each do |test_key, test_value|
|
257
|
+
found_accessor = false
|
258
|
+
found_soda_accrssor = false
|
259
|
+
|
260
|
+
next if (test_key =~ /line_number/)
|
261
|
+
|
262
|
+
supported[test_element]['accessor_attributes'].each do |acc|
|
263
|
+
if (test_key == acc)
|
264
|
+
found_accessor = true
|
265
|
+
break
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
supported[test_element]['soda_attributes'].each do |acc|
|
270
|
+
if (acc.kind_of?(String))
|
271
|
+
if (test_key == acc)
|
272
|
+
found_soda_accrssor = true
|
273
|
+
break
|
274
|
+
end
|
275
|
+
elsif (acc.kind_of?(Hash))
|
276
|
+
if (acc.key?("#{test_key}"))
|
277
|
+
acc[test_key].each do |action|
|
278
|
+
if (test_value == action)
|
279
|
+
found_soda_accrssor = true
|
280
|
+
break
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
if (!found_soda_accrssor)
|
285
|
+
@report.ReportFailure("Faild to find supported action"+
|
286
|
+
" for Soda element: '#{test_element}', attribte: "+
|
287
|
+
"'#{test_key}', action: '#{test_value}', line:"+
|
288
|
+
" #{test_hash['line_number']}!\n")
|
289
|
+
|
290
|
+
$ERROR_COUNT += 1
|
291
|
+
break
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
if ( (found_accessor != true) && (found_soda_accrssor != true) )
|
298
|
+
@report.ReportFailure("(!)Error: Failed to find supported "+
|
299
|
+
"accessor: '#{test_key}'"+
|
300
|
+
" for Soda element: '#{test_element}', line: "+
|
301
|
+
"#{test_hash['line_number']}!\n")
|
302
|
+
|
303
|
+
$ERROR_COUNT += 1
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
private :CheckTest
|
310
|
+
|
311
|
+
###############################################################################
|
312
|
+
# CheckFileformat -- method
|
313
|
+
# This function checks to make sure that the test file format is not DOS.
|
314
|
+
#
|
315
|
+
# Input:
|
316
|
+
# file: the file to check.
|
317
|
+
#
|
318
|
+
# Output:
|
319
|
+
# returns -1 on error, else 0 on success.
|
320
|
+
#
|
321
|
+
###############################################################################
|
322
|
+
def CheckFileformat(file)
|
323
|
+
err = 0
|
324
|
+
|
325
|
+
begin
|
326
|
+
fd = File.open(file, "r")
|
327
|
+
line = fd.readline()
|
328
|
+
fd.close()
|
329
|
+
|
330
|
+
if (line =~ /\r\n$/)
|
331
|
+
@report.ReportFailure("File is in DOS format!\n")
|
332
|
+
err += 1
|
333
|
+
end
|
334
|
+
rescue Exception => e
|
335
|
+
@report.ReportException(e, false, @sodatest)
|
336
|
+
err += 1
|
337
|
+
ensure
|
338
|
+
end
|
339
|
+
|
340
|
+
err = -1 if (err > 0)
|
341
|
+
|
342
|
+
return err
|
343
|
+
end
|
344
|
+
|
345
|
+
end
|
346
|
+
|
347
|
+
|