oats 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.
Files changed (181) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +15 -0
  3. data/README.txt +165 -0
  4. data/Rakefile +2 -0
  5. data/bin/agent +204 -0
  6. data/bin/oats +10 -0
  7. data/bin/occ +29 -0
  8. data/bin/results_cleanup +6 -0
  9. data/doc/COPYING +55 -0
  10. data/doc/LICENSE +55 -0
  11. data/doc/OATS_Framework.doc +0 -0
  12. data/doc/classes/ApplicationLogs.html +239 -0
  13. data/doc/classes/Campaign.html +843 -0
  14. data/doc/classes/CommandlineOptions.html +131 -0
  15. data/doc/classes/Driver.html +182 -0
  16. data/doc/classes/Hash.html +137 -0
  17. data/doc/classes/Ide.html +194 -0
  18. data/doc/classes/MapSelenium.html +197 -0
  19. data/doc/classes/Net.html +107 -0
  20. data/doc/classes/Oats/OatsFilterError.html +119 -0
  21. data/doc/classes/Oats.html +998 -0
  22. data/doc/classes/OatsAssertError.html +119 -0
  23. data/doc/classes/OatsBadInput.html +119 -0
  24. data/doc/classes/OatsData.html +290 -0
  25. data/doc/classes/OatsError.html +117 -0
  26. data/doc/classes/OatsExit.html +117 -0
  27. data/doc/classes/OatsLock.html +254 -0
  28. data/doc/classes/OatsMain.html +182 -0
  29. data/doc/classes/OatsMysqlError.html +113 -0
  30. data/doc/classes/OatsMysqlMissingInput.html +113 -0
  31. data/doc/classes/OatsReportError.html +113 -0
  32. data/doc/classes/OatsSetupError.html +119 -0
  33. data/doc/classes/OatsTestError.html +119 -0
  34. data/doc/classes/OatsTestExit.html +119 -0
  35. data/doc/classes/OatsTestLocateError.html +120 -0
  36. data/doc/classes/OatsVerifyError.html +119 -0
  37. data/doc/classes/Ragent.html +397 -0
  38. data/doc/classes/Rclient.html +236 -0
  39. data/doc/classes/Report.html +368 -0
  40. data/doc/classes/Reports.html +244 -0
  41. data/doc/classes/RestApi.html +333 -0
  42. data/doc/classes/RhttpClient.html +236 -0
  43. data/doc/classes/Rimap.html +170 -0
  44. data/doc/classes/Rmysql.html +176 -0
  45. data/doc/classes/Roptions.html +131 -0
  46. data/doc/classes/Rselenium.html +233 -0
  47. data/doc/classes/Rssh.html +138 -0
  48. data/doc/classes/Runnable.html +174 -0
  49. data/doc/classes/SFTriggers.html +206 -0
  50. data/doc/classes/Selenium/Client/Driver.html +211 -0
  51. data/doc/classes/Selenium/Client.html +107 -0
  52. data/doc/classes/Selenium.html +107 -0
  53. data/doc/classes/SystemCapture.html +304 -0
  54. data/doc/classes/TestCase.html +418 -0
  55. data/doc/classes/TestData.html +235 -0
  56. data/doc/classes/TestList.html +264 -0
  57. data/doc/classes/Tools.html +244 -0
  58. data/doc/classes/Util.html +201 -0
  59. data/doc/classes/Variation.html +206 -0
  60. data/doc/fr_class_index.html +92 -0
  61. data/doc/fr_method_index.html +465 -0
  62. data/doc/index.html +23 -0
  63. data/doc/oats_httpd.conf +32 -0
  64. data/doc/oats_user.yml +25 -0
  65. data/doc/rdoc-style.css +208 -0
  66. data/lib/deep_merge/.gitignore +2 -0
  67. data/lib/deep_merge/core.rb +195 -0
  68. data/lib/deep_merge/deep_merge.rb +1 -0
  69. data/lib/deep_merge/deep_merge_hash.rb +28 -0
  70. data/lib/deep_merge/rails_compat.rb +27 -0
  71. data/lib/oats/application_logs.rb +163 -0
  72. data/lib/oats/build_id.rb +58 -0
  73. data/lib/oats/commandline_options.rb +128 -0
  74. data/lib/oats/diff.rb +278 -0
  75. data/lib/oats/driver.rb +492 -0
  76. data/lib/oats/ide.rb +227 -0
  77. data/lib/oats/keywords.rb +67 -0
  78. data/lib/oats/log4r_init.rb +14 -0
  79. data/lib/oats/mysql.rb +97 -0
  80. data/lib/oats/oats.rb +637 -0
  81. data/lib/oats/oats_data.rb +400 -0
  82. data/lib/oats/oats_exceptions.rb +25 -0
  83. data/lib/oats/oats_lock.rb +261 -0
  84. data/lib/oats/oats_selenium_api.rb +639 -0
  85. data/lib/oats/oselenium.rb +189 -0
  86. data/lib/oats/ossh.rb +36 -0
  87. data/lib/oats/patches_for_eventmachine_12.10.rb +66 -0
  88. data/lib/oats/ragent.rb +321 -0
  89. data/lib/oats/rclient.rb +42 -0
  90. data/lib/oats/report.rb +207 -0
  91. data/lib/oats/roptions.rb +88 -0
  92. data/lib/oats/test_case.rb +510 -0
  93. data/lib/oats/test_data.rb +98 -0
  94. data/lib/oats/test_list.rb +141 -0
  95. data/lib/oats/unixdiff.rb +75 -0
  96. data/lib/oats/util.rb +125 -0
  97. data/lib/oats/version.rb +3 -0
  98. data/lib/oats.rb +36 -0
  99. data/nbproject/configs/agent.properties +0 -0
  100. data/nbproject/configs/gr.properties +0 -0
  101. data/nbproject/project.properties +10 -0
  102. data/nbproject/project.xml +17 -0
  103. data/oats.gemspec +42 -0
  104. data/oats_ini.yml +258 -0
  105. data/oats_tests/Gemfile +18 -0
  106. data/oats_tests/aut_ini.yml +30 -0
  107. data/oats_tests/bin/oats +8 -0
  108. data/oats_tests/environments/qa.yml +4 -0
  109. data/oats_tests/environments/qa_chrome.yml +4 -0
  110. data/oats_tests/examples/core/coreExamples.yml +8 -0
  111. data/oats_tests/examples/core/expectedException.rb +39 -0
  112. data/oats_tests/examples/core/ok_verify.rb +2 -0
  113. data/oats_tests/examples/core/ok_verify.rb_ok/out/myfile.txt +1 -0
  114. data/oats_tests/examples/core/ok_verify.rb_ok/out/myfile2.txt +1 -0
  115. data/oats_tests/examples/core/ok_verify.rb_ok/rats_test.log +2 -0
  116. data/oats_tests/examples/core/unexpectedException.rb +30 -0
  117. data/oats_tests/examples/examples.yml +13 -0
  118. data/oats_tests/examples/gui/guiExamples.yml +7 -0
  119. data/oats_tests/examples/gui/seleniumGoogle.rb +10 -0
  120. data/oats_tests/examples/gui/webdriverGoogle.rb +9 -0
  121. data/oats_tests/examples/keywords/SampleXlList-1.xls +0 -0
  122. data/oats_tests/examples/keywords/SampleXlList-2.xls +0 -0
  123. data/oats_tests/examples/keywords/SampleXlLists.xls +0 -0
  124. data/oats_tests/examples/keywords/keywordsDriver.rb +1 -0
  125. data/oats_tests/examples/keywords/keywordsExamples.yml +8 -0
  126. data/oats_tests/examples/keywords/keywordsTC1.yml +5 -0
  127. data/oats_tests/examples/keywords/keywordsTestlist.yml +16 -0
  128. data/oats_tests/examples/needsWork/addTestDynamically.rb +4 -0
  129. data/oats_tests/examples/needsWork/emailVerify.rb +34 -0
  130. data/oats_tests/examples/needsWork/testSql/rtest.sql +6 -0
  131. data/oats_tests/examples/needsWork/testSql/rtest.yml +11 -0
  132. data/oats_tests/examples/occTest/occTest.rb +13 -0
  133. data/oats_tests/examples/occTest/occTest_1.rb +1 -0
  134. data/oats_tests/examples/occTest/occTest_1_1.rb +1 -0
  135. data/oats_tests/examples/occTest/occTest_1_2.rb +1 -0
  136. data/oats_tests/examples/occTest/occTest_1_3.rb +1 -0
  137. data/oats_tests/examples/occTest/occTest_1_4.rb +1 -0
  138. data/oats_tests/examples/occTest/occTest_2.rb +1 -0
  139. data/oats_tests/examples/occTest/occTest_2_1.rb +1 -0
  140. data/oats_tests/examples/occTest/occTest_2_2.rb +1 -0
  141. data/oats_tests/examples/occTest/occTest_2_3.rb +1 -0
  142. data/oats_tests/examples/occTest/occTest_2_4.rb +1 -0
  143. data/oats_tests/examples/occTest/occTest_3.rb +1 -0
  144. data/oats_tests/examples/occTest/occTest_3_1.rb +1 -0
  145. data/oats_tests/examples/occTest/occTest_3_2.rb +1 -0
  146. data/oats_tests/examples/occTest/occTest_3_3.rb +1 -0
  147. data/oats_tests/examples/occTest/occTest_3_4.rb +1 -0
  148. data/oats_tests/examples/occTest/occTest_4.rb +1 -0
  149. data/oats_tests/examples/occTest/occTestlist.yml +9 -0
  150. data/oats_tests/examples/occTest/occTestlist_1.yml +9 -0
  151. data/oats_tests/examples/occTest/occTestlist_2.yml +9 -0
  152. data/oats_tests/examples/occTest/occTestlist_3.yml +9 -0
  153. data/oats_tests/examples/occTest/variation1.yml +4 -0
  154. data/oats_tests/examples/occTest/variation2.yml +4 -0
  155. data/oats_tests/examples/testFileLocationUnitTests/extn_driver.rb +4 -0
  156. data/oats_tests/examples/testFileLocationUnitTests/folder/oats.yml +3 -0
  157. data/oats_tests/examples/testFileLocationUnitTests/folder/t1.rb +2 -0
  158. data/oats_tests/examples/testFileLocationUnitTests/folder1/t1.yml +2 -0
  159. data/oats_tests/examples/testFileLocationUnitTests/folder1/t1_1.yml +3 -0
  160. data/oats_tests/examples/testFileLocationUnitTests/folder2/oats.yml +3 -0
  161. data/oats_tests/examples/testFileLocationUnitTests/folder2/t1.rb +2 -0
  162. data/oats_tests/examples/testFileLocationUnitTests/folder2/t1.yml +2 -0
  163. data/oats_tests/examples/testFileLocationUnitTests/no_yaml.rb +3 -0
  164. data/oats_tests/examples/testFileLocationUnitTests/post_yaml.rb +1 -0
  165. data/oats_tests/examples/testFileLocationUnitTests/t1.rb +4 -0
  166. data/oats_tests/examples/testFileLocationUnitTests/t1.yml +2 -0
  167. data/oats_tests/examples/testFileLocationUnitTests/t1_1.yml +3 -0
  168. data/oats_tests/examples/testFileLocationUnitTests/testDir/oats.yml +3 -0
  169. data/oats_tests/examples/testFileLocationUnitTests/testDir/t1.rb +2 -0
  170. data/oats_tests/examples/testFileLocationUnitTests/testDir/t1.yml +2 -0
  171. data/oats_tests/examples/testFileLocationUnitTests/testDir2/t1.rb +2 -0
  172. data/oats_tests/examples/testFileLocationUnitTests/testDir2/t1.yml +2 -0
  173. data/oats_tests/examples/testFileLocationUnitTests/unitTestList.yml +36 -0
  174. data/oats_tests/examples/testFileLocationUnitTests/yml_driver.rb +2 -0
  175. data/oats_tests/lib/business.rb +28 -0
  176. data/oats_tests/lib/sample_xl_lists.rb +37 -0
  177. data/test/common_test_unit_setup.rb +21 -0
  178. data/test/test_basic.rb +16 -0
  179. data/test/test_selenium.rb +16 -0
  180. data/test/test_xl_lists.rb +16 -0
  181. metadata +291 -0
data/lib/oats/ide.rb ADDED
@@ -0,0 +1,227 @@
1
+ # IDE Class to run an IDE based HTML suite after transforming it based on oats_data
2
+
3
+ module Oats
4
+
5
+ # Runs an IDE based HTML suite after transforming it based on current Oats data
6
+ class Ide
7
+ def initialize()
8
+ super
9
+ @suite_base_url_signin_type = nil;
10
+ @first_test_url = nil;
11
+ end
12
+
13
+ # Run input_suite_path while in a TestData.dir . Assumes Oats.data is initialized for TestData.dir
14
+ # input_suite_path:: path to the suite HTML
15
+ # hash:: list from => to values to use for regeneration of the included test cases.
16
+ def run (input_suite_path, hash = nil )
17
+ begin
18
+ run_ide(input_suite_path, hash)
19
+ ensure
20
+ TestData.current_test.collect_downloaded_output
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def run_ide (input_suite_path, hash = nil )
27
+ suite_path = get_path(input_suite_path)
28
+ name = File.basename(suite_path)
29
+ doc = open(suite_path ) { |f| Hpricot(f) }
30
+ # FileUtils.rm Dir[File.join(TestData.current_test.dir,'*.gen.*')] # Clean previously generated files
31
+ FileUtils.rm Dir['*.gen.*'] # Clean previously generated files in pwd
32
+ if doc.search("head[@profile='http://selenium-ide.openqa.org/profiles/test-case']").empty?
33
+ regen_suite = nil
34
+ doc.search('a[@href]') do |a|
35
+ if Oats.data['execution']['run_in_dir_results']
36
+ generated_test = regenerate_html(a['href'], test.result, File.dirname(suite_path), hash)
37
+ else
38
+ generated_test = regenerate_html(a['href'], test.dir, File.dirname(suite_path), hash)
39
+ end
40
+ if generated_test
41
+ regen_suite = true
42
+ a.set_attribute(:href,generated_test)
43
+ end
44
+ end
45
+ html_suite_path = File.join(test.dir , File.basename(suite_path,'.*') + '.gen.html')
46
+ regen_suite = true if regen_suite or html_suite_path != suite_path
47
+ html_suite_path = File.join(test.result , File.basename(suite_path,'.*') + '.gen.html') if Oats.data['execution']['run_in_dir_results']
48
+ $log.info "Creating: #{html_suite_path}"
49
+ File.open( html_suite_path, 'w' ) { |out| out.print doc } if regen_suite
50
+ else # A single test HTML, not the suite
51
+ raise OatsTestError, "Input file is not an IDE suite: " + html_suite_path
52
+ end
53
+
54
+ # Execute html_suite_path
55
+ result_file = File.join(test.result, File.basename(name, '.*') + '_results.html')
56
+ if Oats.data['selenium']['ide']['generate']
57
+ $log.warn "Option execution:ide:generate is set. Test will not be executed."
58
+ $log.debug "Target result_file was: #{result_file}"
59
+ return
60
+ end
61
+ rc_jar_file = File.join(Oats.data['_']['vendor'],'selenium-server.jar')
62
+ browser = '*' + Oats.data['selenium']['browser_type'].sub(/ .*/,'')
63
+ url = nil
64
+ if @suite_base_url_signin_type
65
+ url = Oats.data[@suite_base_url_signin_type]["SignIn"]["url"]
66
+ else
67
+ if @first_test_url
68
+ url = @first_test_url
69
+ else
70
+ raise(OatsError, "None of the tests in #{suite_path} specified a base URL.")
71
+ end
72
+ end
73
+ if url
74
+ base_url = url.match('https?://[^/]*/?')
75
+ else
76
+ base_url = nil
77
+ end
78
+ port = Oats.data['selenium']['ide']['port']
79
+ if Oats.data['env']['web']['host']
80
+ base_url = 'http://' + Oats.data['env']['web']['host']
81
+ else
82
+ base_url = base_url[0]
83
+ end
84
+ # if base_url
85
+ # base_url = base_url[0]
86
+ # else
87
+ # base_url = 'http://' + Oats.data['env']['web']['host']
88
+ # $log.warn "Can not determine the base url from [#{url}]. Assuming base url is [#{base_url}]" \
89
+ # unless @suite_base_url_signin_type and Oats.data[@suite_base_url_signin_type]["SignIn"]
90
+ # end
91
+ command = "java -jar \"#{rc_jar_file}\" -port #{port}"
92
+ command += " -timeout #{Oats.data['selenium']['ide']['suite_timeout']}" if Oats.data['selenium']['ide']['suite_timeout']
93
+ # Don't use profiles when using RC in IDE mode
94
+ command += " -firefoxprofileTemplate \"#{$oats_global['firefox_profile_dir']}\"" \
95
+ if Oats.data['selenium']['browser_type'] =~ /firefox/ and $oats_global['firefox_profile_dir']
96
+ command += " -htmlSuite #{browser} #{base_url} \"#{html_suite_path}\" \"#{result_file}\" 2>&1"
97
+ $log.info "Starting Selenium Remote Control: #{command}"
98
+ # return # DEBUG
99
+ first_rc_try = true
100
+ failure_line = nil
101
+ catch :end_rc do
102
+ 2.times do
103
+ IO.popen(command) do |io|
104
+ while io.gets do
105
+ $log.info chomp
106
+ if /Selenium is already running on port/ =~ $_
107
+ if first_rc_try
108
+ io.readlines.each {|line|$log.info line.chomp }
109
+ Util.clear_port(Oats.data['selenium']['ide']['port'],$log)
110
+ $log.info "Will attempt to restart Selenium RC..."
111
+ else
112
+ # raise(OatsError, $_, caller[1..3])
113
+ raise(OatsError, $_)
114
+ throw(:end_rc)
115
+ end
116
+ first_rc_try = false
117
+ elsif /fail/i =~ $_ and /Failed to start: SocketListener/ !~ $_
118
+ failure_line = $_
119
+ throw(:end_rc)
120
+ elsif /exception/i =~ $_ # Like server.SeleniumCommandTimedOutException
121
+ failure_line = $_
122
+ end
123
+ end
124
+ end
125
+ throw(:end_rc) if first_rc_try
126
+ end
127
+ end
128
+ # pause_val = Oats.data['execution']['ide']['pause_on_exit']
129
+ seconds = 999999
130
+ pause_val = $oats['selenium']['pause_on_exit']
131
+ if not pause_val.integer? or
132
+ pause_val <= 0
133
+ seconds = nil
134
+ elsif pause_val == 1
135
+ seconds = nil unless failure_line
136
+ elsif pause_val > 0
137
+ seconds = pause_val
138
+ end
139
+ raise(OatsError, "Result file is not readable: #{result_file}") unless File.readable?(result_file)
140
+ if seconds
141
+ # Need to quote browser path for cygwin because it may have spaces.
142
+ begin
143
+ timeout(seconds) do
144
+ # $stderr.puts "Paused because selenium:pause_on_exit is set to [#{pause_val}]"
145
+ # $stderr.puts "PLEASE HIT <ENTER> TO CONTINUE!"
146
+ successful = system( '"' +Oats.data['selenium']['ide']['result_browser'] + '" file://'+result_file)
147
+ $log.error "Error trying to open results file: #{$?}" \
148
+ unless successful or $? == 256
149
+ end
150
+ rescue Timeout::Error
151
+ end
152
+ end
153
+ TestData.pause_after_error = false
154
+ $log.info "Results are at: file://#{result_file}"
155
+ raise(OatsTestError, failure_line) if failure_line
156
+ end
157
+
158
+ # Helper method to replace HTML file contents based on oats and test data mappings.
159
+ def map_file_contents(oats_data, test_data, file_contents,key_path)
160
+ return unless test_data
161
+ # $log.debug key_path
162
+ if @suite_base_url_signin_type.nil?
163
+ @suite_base_url_signin_type = 'Campaign' if key_path == 'root:Campaign:SignIn'
164
+ @suite_base_url_signin_type = 'Admin' if key_path == 'root:Admin:SignIn'
165
+ # $log.debug "Base URL is set to #{baseUrl}"
166
+ end
167
+ test_data.each do |key,val|
168
+ repVal = oats_data[key]
169
+ next if val.nil? or repVal.nil?
170
+ if val.class == Hash
171
+ map_file_contents( repVal, val, file_contents,key_path + ':' + key)
172
+ else
173
+ file_contents.gsub!(val, repVal.to_s)
174
+ test_data[key] = repVal
175
+ end
176
+ end
177
+ end
178
+
179
+ # Updates HTML file contents based on current oats_data into test_dir_out
180
+ # Returns generated file name or nil if no new file is generated
181
+ def regenerate_html(file_in, dir_out, dir_in = dir_out, hash = nil)
182
+ basename = File.basename(file_in,'.*')
183
+ file_in_absolute = File.expand_path(file_in,dir_in) # get absolute path
184
+ unless File.exist?(file_in_absolute)
185
+ file_in_absolute = Dir.glob( File.join( $oats['execution']['dir_tests'],
186
+ '/**/', file_in.sub(/^(\.\.\/)*/, ''))).first
187
+ # file_in = file_in.sub!(/[^\/]*\//,'')
188
+ raise(OatsError,"Can not locate IDE test case file: [#{file_in}]") unless file_in_absolute
189
+ end
190
+ file_in_root = file_in_absolute.sub(/(.*)\..*$/,'\1')
191
+ yaml_in = file_in_root + '.yml'
192
+ file_out_root = File.join(dir_out, basename)
193
+ file_gen = file_out_root +'.gen.html'
194
+ yml_out = file_out_root +'.gen.yml'
195
+ new_base_name = basename
196
+ if File.exist?(file_gen)
197
+ new_base_name = File.basename(File.dirname(file_in)) + '_' + new_base_name
198
+ file_gen = File.join(dir_out, new_base_name ) +'.gen.html'
199
+ yml_out = File.join(dir_out, new_base_name ) +'.gen.yml'
200
+ end
201
+ if @suite_base_url_signin_type.nil? and @first_test_url.nil?
202
+ doc = open(file_in_absolute) { |f| Hpricot(f) }
203
+ link = doc.at("link[@rel='selenium.base']")
204
+ @first_test_url = link['href'] unless link.nil?
205
+ end
206
+ unless File.exist?(yaml_in)
207
+ return nil if file_in_root == file_out_root
208
+ $log.info "Copying [#{file_in_absolute}] to: #{file_gen}]"
209
+ FileUtils.cp(file_in_absolute, file_gen)
210
+ return basename + '.gen.html'
211
+ end
212
+ $log.debug "Regenerating [#{file_in_absolute}] into [#{file_gen}] based on [#{yaml_in}]"
213
+ file_contents = IO.read(file_in_absolute)
214
+ test_data = YAML.load_file(yaml_in)
215
+ map_file_contents(Oats.data, test_data, file_contents, 'root')
216
+ hash.each { |val, rep_val| file_contents.gsub!(val, rep_val) } if hash
217
+ if Oats.data['selenium']['browser_type'] =~ /iexplore/
218
+ file_contents.sub!(/(<\/IE-ONLY>.*-->)/,'<-- \1')
219
+ file_contents.sub!(/(<!--.*<IE-ONLY>)/,'\1 -->')
220
+ end
221
+ File.open( file_gen, 'w' ) { |out| out.print file_contents }
222
+ File.open( yml_out, 'w' ) { |out| YAML.dump( test_data, out ) }
223
+ basename + '.gen.html'
224
+ end
225
+
226
+ end
227
+ end
@@ -0,0 +1,67 @@
1
+
2
+ module Oats
3
+
4
+ # Process keyword driven testing
5
+ class Keywords
6
+ class << self
7
+
8
+ # Same as selenium.wait_and_type, but maps key via OatsX.locator, and uses
9
+ # OatsX.data[key] for value
10
+ def wait_and_type(key, *args)
11
+ selenium.wait_and_type(locator(key), oats_data[key], *args)
12
+ end
13
+
14
+ # Same as selenium.wait_for_element, but maps key via OatsX.locator first
15
+ def wait_and_click(key)
16
+ selenium.wait_and_click(locator(key))
17
+ end
18
+
19
+ # Same as selenium.wait_for_element, maps key via OatsX.locator first
20
+ def wait_and_text(key)
21
+ selenium.wait_for_element(locator(key)).text
22
+ end
23
+
24
+ # Returned the key or mappings if defined in the <class>::LOCATOR_MAP
25
+ def locator(key)
26
+ self::LOCATOR_MAP[key] || key
27
+ end
28
+
29
+
30
+ # Return data from XL spreadsheet entries via Oats.data('xl.data')
31
+ # OatsX.oats_data(key_string) or OatsX.oats_data[key_string]
32
+ def oats_data(cell = nil, clas = self)
33
+ xl_root = $oats[clas.name]
34
+ list = xl_root['list'] || Oats.data('keywords.list')
35
+ if list
36
+ xl_root_list = xl_root[list]
37
+ else
38
+ xl_root_list = xl_root
39
+ end
40
+ # Oats.assert list, "Oats.data keywords.list is not defined."
41
+ val = cell ? xl_root_list[cell] : xl_root_list
42
+ Oats.assert( val, "No keywords are defined for #{clas}" + (list ? ".#{list}" : '') ) if cell == 'keywords'
43
+ Marshal.load(Marshal.dump(val)) # Protect Oats.data from modification
44
+ end
45
+
46
+ # Handles keyword processing.
47
+ # Used by OATS framework to run XL driven test suites.
48
+ # Users can also call this from yaml_handlers.
49
+ def process
50
+ # Class name comes from Oats.data oats_keywords_cleass, or in the case of XL files from TestCase ID
51
+ class_name = Oats.data('keywords.class') || File.basename(File.dirname(File.dirname(Oats.test.id)))
52
+ begin
53
+ keywords_class = Kernel.const_get class_name
54
+ rescue NameError
55
+ raise OatsTestError, "Can not find class: " + class_name
56
+ end
57
+ oats_data('keywords',keywords_class).each do |action|
58
+ Oats.assert keywords_class.respond_to?(action),
59
+ "There is no method defined in #{class_name} to the handle keyword 'a#{action}'."
60
+ Oats.info "Performing " + action
61
+ keywords_class.send action
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,14 @@
1
+ # Log4r can be configured using YAML. This example uses log4r_yaml.yaml
2
+ require 'log4r'
3
+ require 'log4r/yamlconfigurator'
4
+ # we use various outputters, so require them, otherwise config chokes
5
+ require 'log4r/outputter/datefileoutputter'
6
+ require 'log4r/outputter/emailoutputter'
7
+ include Log4r
8
+
9
+ cfg = YamlConfigurator # shorthand
10
+ cfg['HOME'] = ENV['HOME'] # the only parameter in the YAML, our HOME directory
11
+
12
+ # load the YAML file with this
13
+ cfg.load_yaml_file('log4r.yaml')
14
+
data/lib/oats/mysql.rb ADDED
@@ -0,0 +1,97 @@
1
+ #require 'mysql' # http://www.tmtm.org/en/ruby/mysql
2
+ require "tempfile"
3
+ require 'oats/oats_exceptions'
4
+
5
+ module Oats
6
+ class OatsMysqlError < OatsTestError ; end
7
+ class OatsMysqlMissingInput < OatsMysqlError ; end
8
+ class OatsMysqlNoConnect < OatsMysqlError ; end
9
+ # Oats.mysql creates an instance of this class to interact with MySQL DBs
10
+ class Mysql
11
+
12
+ # See Oats.mysql for more accurate/detailed documentation
13
+ # sql_input:: Path to a file.sql to execute
14
+ # connect:: Override for Oats.data sql:connect
15
+ # returns array of rows of results. Each row is an array of columns.
16
+ def run(sql_input, connect = nil, sql_out_name = nil)
17
+ raise OatsMysqlNoConnect, "Oats.data sql:connect is null" unless Oats.data['sql']['connect']
18
+ test = TestData.current_test
19
+ unless /\s/ =~ sql_input # If there is space in name, assume it is not a file
20
+ abs_path = File.expand_path(sql_input,test.path)
21
+ end
22
+ if File.exist?(abs_path)
23
+ mysql_input_file = OatsData.regenerate_file(abs_path)
24
+ mysql_input_file = abs_path unless mysql_input_file
25
+ name = File.basename(sql_input,'.*')
26
+ sql_input = IO.read(mysql_input_file)
27
+ sql_input = nil if sql_input.length > 200
28
+ else
29
+ tf = Tempfile.new("OatsMysqlInput")
30
+ tf.puts(sql_input)
31
+ tf.close
32
+ mysql_input_file = Util.expand_path(tf.path)
33
+ name = 'mysql_default'
34
+ end
35
+ sql_out_name = name + '.txt' unless sql_out_name
36
+ sql_out = File.join(test.result, sql_out_name) if sql_out_name
37
+ err_file = sql_out + '.err'
38
+ command = (ENV['OS'] != 'Darwin' ? 'mysql' : '/usr/local/mysql/bin/mysql') +
39
+ " #{parameters(connect)} < #{mysql_input_file} > #{sql_out} 2> #{err_file}"
40
+ # $log.debug "Executing: #{command}"
41
+ $log.info "SQL: #{sql_input}" if sql_input
42
+ FileUtils.mkdir_p(test.out)
43
+ ok = system(command)
44
+ $log.error("MySQL failed with return code: #{$?}") unless ok
45
+ FileUtils.rm_f(err_file) unless File.size?(err_file)
46
+ FileUtils.rm_f(sql_out) unless File.size?(sql_out)
47
+ if File.exist?(err_file)
48
+ errors = IO.readlines(err_file)
49
+ errors.size == 1 or errors[0...-1].each {|line| $log.error line.chomp}
50
+ raise(OatsMysqlError,errors.last.chomp) unless errors.empty?
51
+ end
52
+ rows = IO.readlines(sql_out) if File.exist?(sql_out)
53
+ return [] unless rows
54
+ rows.shift
55
+ if rows[1] =~ /\t/
56
+ return rows.collect{|t| t.chomp.split(/\t/) }
57
+ else
58
+ return rows.collect{|t| t.chomp }
59
+ end
60
+ end
61
+
62
+
63
+ def processlist
64
+ raise OatsMysqlNoConnect, "Oats.data sql:connect is null" unless Oats.data['sql']['connect']
65
+ sql_out = 'mysql_processlist.txt'
66
+ command = "mysqladmin #{parameters('connect',true)} processlist > #{sql_out}"
67
+ success = system(command)
68
+ $log.error("MySQL failed with return code: #{$?}") unless success
69
+ FileUtils.rm_f(sql_out) unless File.size?(sql_out)
70
+ end
71
+
72
+ private
73
+
74
+ def parameters(connect,proc_list=false)
75
+ sql = Oats.data['sql']
76
+ connect ||= sql['connect']
77
+ conn = sql[connect]
78
+ user = conn['user']
79
+ err "Oats MySQL requires input for sql:user" unless user
80
+ password = conn['password']
81
+ err "Oats MySQL requires a string input for sql:password" unless password
82
+ password = " -p#{password}" unless password == ""
83
+ host = conn['host']
84
+ err "Oats MySQL requires input for sql:host" unless host
85
+ params = "-u#{user}#{password} -h#{host}"
86
+ return params if proc_list
87
+ db = conn['database']
88
+ err "Oats MySQL requires input for sql:db" unless db
89
+ "#{params} -D#{db}"
90
+ end
91
+
92
+ def err(inp)
93
+ raise(OatsMysqlMissingInput,inp)
94
+ end
95
+
96
+ end
97
+ end