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/oats.rb ADDED
@@ -0,0 +1,637 @@
1
+ require 'oats/util'
2
+ require 'oats/oats_exceptions'
3
+ # Need these set for OCC when this is required from OCC
4
+ ENV['OATS_HOME'] ||= File.expand_path( '..', File.dirname(__FILE__) )
5
+ ENV['OATS_TESTS'] ||= (ENV['OATS_HOME'] + '/oats_tests')
6
+
7
+ module Oats
8
+
9
+ # Main method that starts oats execution.
10
+ # Parameters are command-line arguments
11
+ # Returns oats_info object containing execution results
12
+ def Oats.run(args = nil)
13
+ Driver.run(args)
14
+ end
15
+
16
+ # Registers classes to initialize class methods by calling call <Class>.init before
17
+ # each TestList execution. To use, put inside the class: Oats.testlist_init(self)
18
+ def Oats.testlist_init(klas, *args)
19
+ $oats_execution['testlist_init'] ||= {}
20
+ $oats_execution['testlist_init'][klas] = args
21
+ end
22
+
23
+ # Merges indicated YAML into the test's Oats.data
24
+ def Oats.yaml(yaml_file)
25
+ OatsData.include_yaml_file yaml_file
26
+ end
27
+
28
+ # Adds new test to the current test_files
29
+ # OatsTest.names method(s) should be defined under the OatsTest module in the lib
30
+ # Example:
31
+ # Oats.add_test Oats.add_test "method_test", "testid_#{i}", "parameter_#{i}"
32
+ # module OatsTest # Place this definition in the 'lib' to be auto-required
33
+ # def self.method_test(params)
34
+ # Oats.info "Running new test: #{Oats.test.id} with params: #{params.inspect}"
35
+ # end
36
+ # end
37
+ def Oats.add_test(*args)
38
+ # Oats.assert self.respond_to?(name), "Method OatsTest.#{names} is not defined."
39
+ # args[0] = TestData.current_test.dir.sub(/\.rb/,".#{args[0]}.methodTest")
40
+
41
+ # args.unshift TestData.current_test.dir
42
+ $oats_global['test_files'] ||= []
43
+ $oats_global['test_files'].push(args[0])
44
+ end
45
+
46
+ # Raises OatsAssertError unless is includer.include?(includee) is true
47
+ # If given pre_message preceeds the standard message showing expected and actuals.
48
+ # Example:
49
+ # Oats.assert_include('is','this, "Should never fail")
50
+ def Oats.assert_include?(includee, includer, pre_message = nil)
51
+ pre_message += ' ' if pre_message
52
+ Oats.assert(includer.include?(includee),"#{pre_message} Failed since #{includer.inspect} does not include #{includee.inspect}")
53
+ end
54
+ # Raises OatsAssertError unless two parameters are '=='
55
+ # If given pre_message preceeds the standard message showing expected and actuals.
56
+ # Example:
57
+ # Oats.assert_equal(old_count, new_count, "After deletion, creative counts did not decrease.")
58
+ def Oats.assert_equal(expected, actual, pre_message = nil)
59
+ pre_message += ' ' if pre_message
60
+ Oats.assert(expected == actual,"#{pre_message}Expected value #{expected.inspect} does not match actual #{actual.inspect}")
61
+ end
62
+ # Raises OatsAssertError if two parameters are '=='
63
+ def Oats.assert_not_equal(expected, actual, pre_message = nil)
64
+ pre_message += ' ' if pre_message
65
+ Oats.assert(expected != actual,"#{pre_message}Expected different but received the same value: #{actual.inspect}")
66
+ end
67
+ # Raises OatsTestError unless test is true
68
+ def Oats.assert(test, message = nil)
69
+ message = 'Assertion failed.' unless message
70
+ raise(OatsAssertError, message) unless test
71
+ end
72
+
73
+ # Returns a browser (selenium driver), logging into RL site or opening URL.
74
+ # The browser is retrieved and reused in the subsequent rtest.*rb executions,
75
+ # but it is automatically closed at the end of each Oats test. If exists, the
76
+ # browser is also accessible via the global $selenium.
77
+ # The arguments url_or_site and credentials will be passed to Oselenium.login
78
+ #
79
+ # Parameters:
80
+ # url_or_site:: String, A URL, or site:
81
+ # [root@oats ]
82
+ # Required parameter for the first invocation, can be
83
+ # omitted in subsequent invocations to get the current browser.
84
+ # Re-issueing it w/o logging out of the same site will reopen
85
+ # the landing page. A different site will cause logout of the
86
+ # old site and login to the new site. User will be created if
87
+ # it does not already exists.
88
+ # new_browser:: If true, will create a new browser while keeping the old one.
89
+ # credentials:: Hash to contain credentials['email'] and, credentials['password']
90
+ #
91
+ # Methods in addition to the selenium driver methods are:
92
+ # login(site):: Same as Oats.browser(url_or_site), for a site. Returns nil if
93
+ # site is not recognized.
94
+ # logout:: Logs out of the last logged in sites if any and returns browser.
95
+ # Logout may not succeed if logout button is unavailable.
96
+ #
97
+ # Examples:
98
+ # browser = Oats.browser('oats')
99
+ # browser.click("link=Orders")
100
+ # browser.login('root@')
101
+ # browser.logout
102
+ #
103
+ def Oats.browser(*args)
104
+ require 'oats/oselenium' unless defined?(Oats::Oselenium)
105
+ Oselenium.browser(*args)
106
+ end
107
+
108
+ # Capture system screenshot and logs
109
+ # Returns captured file name if successful, or nil.
110
+ def Oats.system_capture
111
+ return if $selenium.nil? or # Snapshots are not supported on Ubuntu/Chrome
112
+ ($oats['selenium']['browser_type'] == 'chrome' and ENV['OS'] == 'Linux')
113
+ ct = TestData.current_test
114
+ file = Util.file_unique(fn="page_screenshot.png", ct.result)
115
+ Oats.info "Will attempt to capture #{fn}."
116
+ begin
117
+ timeout($oats['selenium']['capture_timeout']) { selenium.save_screenshot(file) }
118
+ ct.error_capture_file = fn
119
+ rescue Exception => e
120
+ $log.warn "Could not capture page screenshot: #{e}"
121
+ end
122
+ return ct.error_capture_file
123
+ end
124
+
125
+ # Loads the indicated ruby file file after locating it in the tests directory.
126
+ #
127
+ # Parameters:
128
+ # ruby_file_name: Name or path snippet of a the ruby file. Could be a glob.
129
+ #
130
+ # Examples:
131
+ # Oats.oload 'rtest_AddCreatives'
132
+ # Oats.oload 'verifyAddCreatives/rtest_Add*'
133
+ def Oats.oload(ruby_file_name)
134
+ file = TestCase.locate_test_rb(ruby_file_name)
135
+ if file
136
+ begin
137
+ Oats.debug "Loading rb file: #{file}"
138
+ Oats.global['oloads'].push file
139
+ load(file)
140
+ ensure
141
+ Oats.debug "Finished rb file: #{file}"
142
+ Oats.global['oloads'].pop
143
+ end
144
+ else
145
+ raise OatsError, "Can not locate ruby file to load: #{ruby_file_name}"
146
+ end
147
+ end
148
+
149
+ # Hash object providing access to the oats.yml state entries at the time of
150
+ # test execution. Note that Oats.data contents are isolated from modification
151
+ # across tests. If path is not found, returns nil unless do_raise_if_missing
152
+ # is set.
153
+ # map_string:: Period seperated YAML path into the current Oats.data
154
+ # If not specified, returns the full hash.
155
+ # do_raise_if_missing:: set true to raise OatsTestError if key is missing
156
+ # Examples:
157
+ # Oats.data 'selenium.browser' == 'firefox
158
+ # Oats.data['selenium']['browser'] == 'firefox'
159
+ def Oats.data(map_str = nil, do_raise_if_missing = nil)
160
+ return $oats unless map_str
161
+ data_keys = map_str.split('.')
162
+ value = $oats
163
+ # until ! value.kind_of?(Hash) or data_keys.size == 0 do
164
+ loop do
165
+ return value if data_keys.empty?
166
+ if value.instance_of? Hash
167
+ key = data_keys.shift
168
+ if do_raise_if_missing
169
+ Oats.assert(value.has_key?(key), "Can not locate #{key} for #{map_str} at ")
170
+ end
171
+ value = value[key]
172
+ else
173
+ return nil
174
+ end
175
+ end
176
+ end
177
+
178
+ # Adjust result dir YAML entries if running on agent mode
179
+ def Oats.result_archive_dir
180
+ return $oats['result_archive_dir'] if $oats['result_archive_dir']
181
+ oats_data = $oats
182
+ oats_data['execution']['dir_results'] = Util.expand_path(oats_data['execution']['dir_results'])
183
+ oats_data['result_archive_dir'] = oats_data['execution']['dir_results'] + '_archive'
184
+ if $oats_execution['agent']
185
+ agent_nickname = Ragent.occ['agent_nickname']
186
+ if oats_data['execution']['dir_results'] !~ /#{agent_nickname}$/
187
+ # Should move to a better place.This is unrelated to results, Just picking up the agent file.
188
+ agent_ini_file = File.join(ENV['HOME'], agent_nickname + '_oats.yml')
189
+ oats_data = OatsData.load(agent_ini_file,oats_data) if File.exist?(agent_ini_file)
190
+ oats_data['result_archive_dir'] += '/' + agent_nickname
191
+ oats_data['execution']['dir_results'] += '/' + agent_nickname
192
+ end
193
+ end
194
+ FileUtils.mkdir_p(oats_data['result_archive_dir'])
195
+ return oats_data['result_archive_dir']
196
+ end
197
+
198
+ # Returns input or ''. Used to force ruby eval of Oat.data YML values
199
+ def Oats.eval(input=nil)
200
+ return input || ''
201
+ end
202
+ # Returns hash object containing info about persistent oats internal variables
203
+ # for the complete oats execution. Contents of Oats.context are also persisted into
204
+ # the results.dump in the results directory.
205
+ #
206
+ # Examples:
207
+ # Oats.context['stop_oats'] == true # Request stopping oats after current test
208
+ def Oats.context
209
+ $oats_info
210
+ end
211
+
212
+ # Output debug level log entries.
213
+ def Oats.debug(arg)
214
+ $log.debug(arg)
215
+ end
216
+
217
+ # Output error level log entries.
218
+ def Oats.error(arg)
219
+ ex = OatsTestError.exception(arg.to_s)
220
+ TestData.error(ex)
221
+ $log.error(arg)
222
+ end
223
+
224
+ # Exit a OATS Test from the middle without throwing an error.
225
+ def Oats.exit(message=nil)
226
+ raise OatsTestExit, message if message
227
+ raise OatsTestExit
228
+ end
229
+
230
+ # Raise OatsTestExit and SKIP current test if there was a previous test and
231
+ # if previous test dif not pass or or_if_true is true
232
+ def Oats.skip_unless_previous_test_is_ok(or_if_true = false)
233
+ return unless TestData.previous_test
234
+ if or_if_true or TestData.previous_test.status != 0
235
+ Oats.data['execution']['no_run'] = true
236
+ Oats.exit "Skipping this test since previous test did not pass."
237
+ end
238
+ end
239
+
240
+ # Exception raised by Oats.filter
241
+ class OatsFilterError < OatsError ; end
242
+
243
+ # Returns Windows file path of a file name to be used with file uploads.
244
+ # name:: globbed file name inside the test directory or under test/data folder.
245
+ # Examples:
246
+ # image = Oats.file "125x125_GIF_4K.gif"
247
+ def Oats.file(name)
248
+ file = name if File.exist?(name)
249
+ file = Dir.glob(File.join(Oats.test.path, name)).first unless file
250
+ file = Dir.glob(File.join( $oats['execution']['dir_tests'], 'data', '**',name)).first unless file
251
+ Oats.assert file, "Can not locate file with name [#{name}]"
252
+ Oselenium.remote_webdriver_map_file_path(file)
253
+ end
254
+
255
+
256
+ # Moves files downloaded by selenium into the test.result directory.
257
+ # Input is shell glob names, defaulting to '*'.
258
+ # Returns array of basenames of copied files.
259
+ # Assumes downloaded file is not empty
260
+ def Oats.collect_downloaded(file_glob_name = '*')
261
+ downloaded_files = []
262
+ result_dir = TestData.current_test.result
263
+ # cur_test.collect_downloaded_output if cur_test && cur_test.instance_of?(TestCase)
264
+ Oats.wait_until("There were no files in: #{$oats_global['download_dir']}", 15) do
265
+ Dir.glob(File.join($oats_global['download_dir'],file_glob_name)) do |e|
266
+ # Ensure file is fully downloaded
267
+ old_size = 0
268
+ Oats.wait_until do
269
+ new_size = File.size?(e) # Returns nil if size is zero. Assumes downloaded file is not empty
270
+ if new_size and new_size == old_size # File size stabilized
271
+ FileUtils.mv(e, result_dir )
272
+ downloaded_files.push(File.basename(e))
273
+ else
274
+ old_size = new_size
275
+ false
276
+ end
277
+ end
278
+ end
279
+ downloaded_files != []
280
+ end
281
+ return downloaded_files
282
+ end
283
+
284
+
285
+ # Removes the random words from files in 'Oats.test.result' by applying
286
+ # prescribed filter to each line of file and replaces it. The return value is
287
+ # the filtered contents of the file. The filtered contents are also placed in
288
+ # test.out to be compared as expected results. Errors will raise OatsFilterError.
289
+ # * With a block replaces each line with result of the block.
290
+ # * Without block, uses a pattern and replacement parameters for filtering.
291
+ # * If pattern and replacement is missing it copies the whole input file.
292
+ # * If in_file is a string, no output file is generated unless out_file is given.
293
+ #
294
+ # Parameters:
295
+ # in_file:: Name or path of file that is to be filtered and moved to
296
+ # Oats.test.out. It can also be String Array or String containing the
297
+ # actual contents. If the file contains a space, it is assumed to be
298
+ # contents. Missing input or file raises OatsFilterError.
299
+ # out_file:: File name to use for the output file. This is an optional
300
+ # parameter which can be skipped. If skipped, basename of the
301
+ # infile is used.
302
+ # pattern:: A regexp pattern to pass on to a gsub or grep method. Grep is
303
+ # used if replacement parameter is unspecified, in other words
304
+ # file_contents.grep(/pattern_string/)
305
+ # replacement:: Fixed string to replace the pattern by calling
306
+ # file_contents.gsub(pattern,replacement)
307
+ #
308
+ # Examples:
309
+ # Oats.filter('input.txt') # Moves input.txt to test.out for auto-verification.
310
+ # Oats.filter('input.txt','output.txt,/this/) # Considers only lines containing 'this'
311
+ # Oats.filter('input.txt',/this.*that/,'thisAndThat') # Replaces indicated content
312
+ # Oats.filter('input.txt') { |line| line unless line == 'this\n' } # Omits 'this\n' line
313
+ def Oats.filter(in_file, *param)
314
+ raise(OatsFilterError,"At least one inputis required.") unless in_file
315
+ test = TestData.current_test
316
+ case in_file
317
+ when String
318
+ raise(OatsFilterError,"Input string can not be empty.") if in_file == ''
319
+ if /\s/ =~ in_file # If there is space in name, assume it is not a file
320
+ input_is_file = false
321
+ lines = in_file.split($/)
322
+ else
323
+ input_is_file = true
324
+ if File.exist?(in_file)
325
+ filter_file = Util.expand_path(in_file)
326
+ else
327
+ in_files = Dir[in_file]
328
+ filter_file = in_files[0] unless in_files.empty?
329
+ end
330
+ unless filter_file
331
+ result_dir = test.result
332
+ filter_file = Util.expand_path(in_file, result_dir)
333
+ filter_file = nil unless File.exist?(filter_file)
334
+ end
335
+ unless filter_file
336
+ filter_file = Util.expand_path(in_file, result_dir)
337
+ in_files = Dir[filter_file]
338
+ if in_files.empty?
339
+ filter_file = nil
340
+ else
341
+ filter_file = in_files[0]
342
+ end
343
+ end
344
+ raise(OatsFilterError,"Can not locate file to filter: [#{in_file}] in: " + result_dir) unless filter_file
345
+ raise(OatsFilterError,"Can not read file to filter: #{filter_file}") unless File.readable?(filter_file)
346
+ end
347
+ when Array
348
+ input_is_file = false
349
+ lines = in_file
350
+ else
351
+ raise(OatsFilterError,'Unrecognized input type.')
352
+ end
353
+
354
+ if not param.empty? and param[0].instance_of?(String)
355
+ out_file = File.join(test.out, File.basename(param[0]))
356
+ param.shift
357
+ elsif input_is_file
358
+ out_file = File.join(test.out, File.basename(filter_file))
359
+ else
360
+ out_file = nil
361
+ end
362
+ FileUtils.mkdir_p(test.out) if test.out
363
+ if param.empty?
364
+ pattern = nil
365
+ else
366
+ pattern = param[0]
367
+ param.shift
368
+ end
369
+ if param.empty?
370
+ replacement = nil
371
+ else
372
+ replacement = param[0]
373
+ param.shift
374
+ end
375
+ lines = IO.readlines(filter_file) if input_is_file
376
+ # FileUtils.rm(filter_file)
377
+ out_lines = if block_given?
378
+ lines.collect { |line| yield(line) }
379
+ elsif replacement
380
+ lines.collect { |line| line.sub!(pattern,replacement) }
381
+ elsif pattern
382
+ lines.grep(pattern)
383
+ else
384
+ if out_file and filter_file
385
+ FileUtils.cp(filter_file, out_file) # Do not mv here.
386
+ # Otherwise out_file can not produce unique files
387
+ return lines ? lines : []
388
+ end
389
+ lines ? lines : []
390
+ end
391
+
392
+ if out_lines
393
+ out_lines.delete_if{ |line| line.chomp == '' } unless out_lines.empty?
394
+ if out_file and not out_lines.empty?
395
+ File.open(out_file,'a+') { |ios| ios.write(out_lines.join) }
396
+ end
397
+ else
398
+ out_lines = []
399
+ end
400
+ out_lines
401
+ end
402
+
403
+ # Creates a file handle to output into the out directory with given name
404
+ # Returns the comparison with any previous ok file if exists.
405
+ #
406
+ # Parameters:
407
+ # file_name: Appends '_<count>' to the this name if the file already exists.
408
+ # content: String to output, must supply only if a block is not given.
409
+ # no_raise: If set to true, just return comparison, don't raise exception
410
+ # Examples:
411
+ # Oats.out_file('my_file.txt', "Check this string" }
412
+ # Oats.out_file('my_file.txt') { |f| f.puts "Check this string" }
413
+ def Oats.out_file(file_name, content = nil, no_raise = nil)
414
+ out_path = Util.file_unique(file_name, Oats.test.result)
415
+ File.open(out_path, 'w+') do |f|
416
+ if block_given?
417
+ yield f
418
+ else
419
+ f.puts content
420
+ end
421
+ end
422
+ Oats.assert(File.exist?(out_path), "Can not find file #{out_path}") # Verify did create the file
423
+ File.basename(out_path)
424
+ # file_ok = File.join Oats.test.ok_out, basename
425
+ # is_ok = true
426
+ # if File.exist?(file_ok)
427
+ # is_ok = FileUtils.compare_file(out_path, file_ok)
428
+ # Oats.assert is_ok || no_raise, "Found differences in file: #{file_ok}"
429
+ # Oats.info "Matched ok contents [#{content||basename}"
430
+ # end
431
+ # return is_ok
432
+ end
433
+
434
+
435
+ # Runs the input_suite_path from a particular Oats.test. Assumes Oats.data is
436
+ # initialized for Oats.test
437
+ #
438
+ # Parameters:
439
+ # input_suite_path:: path to the IDE suite HTML
440
+ # hash:: list from => to values to use for regeneration of the included test
441
+ # cases.
442
+ #
443
+ # Examples:
444
+ # Oats.ide.run('../campaign/rtest.html', 'this_token" => 'that_value')
445
+ def Oats.ide(input_suite_path, hash = nil )
446
+ $ide.run(input_suite_path, hash )
447
+ end
448
+
449
+ # Obsolete. Create classes and use class variables to carry over global info.
450
+ def Oats.global
451
+ $oats_global
452
+ end
453
+
454
+ # Output info level log entries.
455
+ def Oats.info(arg)
456
+ # return if arg.nil?
457
+ arg = arg.inspect unless arg.instance_of?(String)
458
+ $log.info(arg)
459
+ end
460
+
461
+
462
+
463
+ # Execute MySQL files or statements, return result set in an array of rows.
464
+ # Empty result set results in an empty array. First row [0] of the result
465
+ # contains the column headers. If each row has multiple fields, the row is
466
+ # returned in an array of strings. Otherwise each row a string containing the
467
+ # single column value.
468
+ #
469
+ # Parameters:
470
+ # sql_input:: String denoting a file or SQL content (assumed if s has a space)
471
+ # connect:: Override for Oats.data sql:connect
472
+ # sql_out_name:: File name to place the SQL output into the test.out directory.
473
+
474
+ # Examples
475
+ # Oats.mysql('input.sql') => produces input.txt and returns its contents
476
+ # Oats.mysql('input.sql', 'output.txt) => produces output.txt and returns its contents
477
+ # mysql_results = Oats.mysql "SELECT bu_lastname, FROM BusinessUser where bu_email='levent.atasoy@oats.org;XYZ'"
478
+ # result = Oats.mysql(my_sql_statement)
479
+ # result.is_empty? # true if SQL returns nothing
480
+ # result.last # string value for the last row of a single select statement
481
+ # result[1][2] # second column for the first return result row
482
+
483
+ def Oats.mysql(*sql_input)
484
+ require 'oats/mysql' unless defined?(Oats::Mysql) == 'constant'
485
+ $mysql ||= Oats::Mysql.new
486
+ $mysql.run(*sql_input)
487
+ end
488
+
489
+ # Executes a script on an server via ssh using PuTTy/plink
490
+ # Assumes pageant with keys for the username is up and running.
491
+ # Returns the result of the standard output and standard error.
492
+ #
493
+ # Parameters:
494
+ # cmd_file:: Path of the executable relative to dir
495
+ # dir:: Directory to cd prior to executing cmd_file. Home of user if omitted.
496
+ # host/session: Name for putty on which to execute cmd_file. Defaults via Oats.data
497
+ # username:: Putty connection data Login username. Defaults via Oats.data.
498
+ # If username is 'root', executes the cmd_file as sudo root with
499
+ # Oats.data[ssh.root_sudo_username].
500
+ # root_sudo_username must be able to
501
+ # - access host via Plink/Pageant
502
+ # - sudo -s on the host
503
+ # - cd to dir without being root.
504
+ #
505
+ # Examples
506
+ # out = Oats.rssh('/home/transfer.pl')
507
+ # Oats.rssh('./transfer.pl', /home')
508
+ # Oats.rssh('cat that.log','/var/www/app')
509
+ # Oats.rssh('ls httpd', '/var/log', nil, 'root')
510
+ def Oats.rssh(cmd_file, dir = nil , host = nil, username = nil)
511
+ Ossh.run(cmd_file, dir, host, username )
512
+ end
513
+
514
+ # Copies a file to the server via ssh using PuTTy/plink
515
+ # Assumes pageant with keys for the username is up and running.
516
+ # Returns the result of the standard output and standard error, which is
517
+ # typically empty.
518
+ #
519
+ # Parameters:
520
+ # content_file:: Path of the content file, or the content string if file
521
+ # does not exist.
522
+ # target_file_path:: Path of the file on the server
523
+ # host/session: Same parameter as in Oats.rssh
524
+ # username:: Same parameter as in Oats.rssh
525
+ #
526
+ # Examples
527
+ # Oats.rput 'xxx xxxxxxx', '/tmp/myfile.txt' , 'qapp001.dyn.wh.oats.org'
528
+ # Oats.rput 'c:/qa/oats-user.yml', '/tmp/myfile.txt' , 'qapp001.dyn.wh.oats.org'
529
+ def Oats.rput(content_file, target_file_path = nil, host = nil, username = nil)
530
+ Ossh.run(content_file, target_file_path, host, username, true)
531
+ end
532
+
533
+ # Returns the current TestData object. You can use the public instance methods
534
+ # of TestCase to access to test path components or other test information.
535
+ def Oats.test
536
+ TestData.current_test
537
+ end
538
+
539
+ # Samples the given block each second until it returns true or times out.
540
+ # Raises OatsTestError if times out or returns last value of block.
541
+ #
542
+ # Parameters (also allowed as Hash):
543
+ # :message Exception message to issue upon timeout.
544
+ # Appended with 'in N seconds' unless seconds is negative.
545
+ # :seconds For timeout, defaults from Oats.data selenium.command_timeout
546
+ # :is_return Returns false if times out instead of raising OatsTestError.
547
+ # If :message is nil, :is_return defaults to true
548
+ # :interval Seconds to wait in betweeen calls to block
549
+ #
550
+ # Example:
551
+ # wait_str = 'loadingIcon'
552
+ # Oats.wait_until("Page did not have [#{wait_str}]") {
553
+ # $selenium.get_html_source.include?(wait_str)
554
+ # }
555
+ def Oats.wait_until(*args)
556
+ raise(OatsTestError, 'Oats.wait_until requires an input block.') unless block_given?
557
+ if args[0].kind_of?(Hash)
558
+ options = args[0]
559
+ message = options[:message]
560
+ seconds = options[:seconds]
561
+ is_return = options[:is_return]
562
+ interval = options[:interval]
563
+ else
564
+ message, seconds, is_return, interval = *args
565
+ end
566
+ interval ||= 1
567
+ seconds ||= Oats.data['execution']['wait_until_timeout']
568
+ is_return = true if message.nil?
569
+ if seconds < 0
570
+ seconds = seconds.abs
571
+ message += " in #{seconds} seconds"
572
+ end
573
+ begin
574
+ return_val = false
575
+ Timeout::timeout seconds do
576
+ loop do
577
+ return_val = yield
578
+ break if return_val
579
+ sleep interval
580
+ end
581
+ return return_val
582
+ end
583
+ rescue Timeout::Error
584
+ if is_return
585
+ Oats.warn message if message
586
+ return false
587
+ else
588
+ raise(OatsTestError, message) if message
589
+ raise OatsTestError
590
+ end
591
+ end
592
+ end
593
+
594
+ # Returns a unique string for each machine for each call.
595
+ # The string will start with the input prefix if supplied.
596
+ # If the input prefix matches the pattern of unique output, then only the
597
+ # unique suffix is modified.
598
+ #
599
+ # Parameters:
600
+ # prefix:: Prefix string to use.
601
+ #
602
+ # Examples:
603
+ # Oats.unique => "mach_83580508"
604
+ # Oats.unique('this') => "this-835805081"
605
+ # Oats.unique(Oats.unique('this')) => "this-835805082"
606
+ def Oats.unique(prefix = nil)
607
+ agent = $oats_execution['agent'] ? $oats_execution['agent']['execution:occ:agent_nickname'] : nil
608
+ prefix = ENV['HOSTNAME'].sub(/\..*/,'').downcase unless prefix or agent
609
+ postfix = (agent ? agent + '_' : '') + Time.now.to_i.to_s[-8..-1]
610
+ if Oats.global['unique']
611
+ extra = Oats.global['unique'].sub(/#{postfix}/,'')
612
+ unless extra == Oats.global['unique']
613
+ if extra == ''
614
+ postfix = "#{postfix}1"
615
+ else
616
+ postfix = postfix + ((extra.to_i) + 1).to_s
617
+ end
618
+ end
619
+ end
620
+ Oats.global['unique'] = postfix
621
+ if prefix
622
+ separator = '-'
623
+ else
624
+ prefix = ''
625
+ separator = ''
626
+ end
627
+ postfix_pattern = separator + (agent ? agent + '_' : '') + '\d\d\d\d\d\d\d\d\d*'
628
+ return prefix.sub(/#{postfix_pattern}$/, '') + separator + "#{postfix}"
629
+ end
630
+
631
+ # Output warning level log entries.
632
+ def Oats.warn(arg)
633
+ $log.warn(arg)
634
+ end
635
+
636
+ end
637
+