oats 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ *.gemspec
@@ -0,0 +1,195 @@
1
+ module DeepMerge
2
+
3
+ class InvalidParameter < StandardError; end
4
+
5
+ # DEFAULT_FIELD_KNOCKOUT_PREFIX = '--'
6
+
7
+ # Deep Merge core documentation.
8
+ # deep_merge! method permits merging of arbitrary child elements. The two top level
9
+ # elements must be hashes. These hashes can contain unlimited (to stack limit) levels
10
+ # of child elements. These child elements to not have to be of the same types.
11
+ # Where child elements are of the same type, deep_merge will attempt to merge them together.
12
+ # Where child elements are not of the same type, deep_merge will skip or optionally overwrite
13
+ # the destination element with the contents of the source element at that level.
14
+ # So if you have two hashes like this:
15
+ # source = {:x => [1,2,3], :y => 2}
16
+ # dest = {:x => [4,5,'6'], :y => [7,8,9]}
17
+ # dest.deep_merge!(source)
18
+ # Results: {:x => [1,2,3,4,5,'6'], :y => 2}
19
+ # By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
20
+ # To avoid this, use "deep_merge" (no bang/exclamation mark)
21
+ #
22
+ # Options:
23
+ # Options are specified in the last parameter passed, which should be in hash format:
24
+ # hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
25
+ # :preserve_unmergeables DEFAULT: false
26
+ # Set to true to skip any unmergeable elements from source
27
+ # :overwrite_arrays DEFAULT: false
28
+ # Set to true to not merge but overwrite arrays
29
+ # :knockout_prefix DEFAULT: nil
30
+ # Set to string value to signify prefix which deletes elements from existing element
31
+ # :sort_merged_arrays DEFAULT: false
32
+ # Set to true to sort all arrays that are merged together
33
+ # :unpack_arrays DEFAULT: nil
34
+ # Set to string value to run "Array::join" then "String::split" against all arrays
35
+ # :merge_debug DEFAULT: false
36
+ # Set to true to get console output of merge process for debugging
37
+ #
38
+ # Selected Options Details:
39
+ # :knockout_prefix => The purpose of this is to provide a way to remove elements
40
+ # from existing Hash by specifying them in a special way in incoming hash
41
+ # source = {:x => ['--1', '2']}
42
+ # dest = {:x => ['1', '3']}
43
+ # dest.ko_deep_merge!(source)
44
+ # Results: {:x => ['2','3']}
45
+ # Additionally, if the knockout_prefix is passed alone as a string, it will cause
46
+ # the entire element to be removed:
47
+ # source = {:x => '--'}
48
+ # dest = {:x => [1,2,3]}
49
+ # dest.ko_deep_merge!(source)
50
+ # Results: {:x => ""}
51
+ # :unpack_arrays => The purpose of this is to permit compound elements to be passed
52
+ # in as strings and to be converted into discrete array elements
53
+ # irsource = {:x => ['1,2,3', '4']}
54
+ # dest = {:x => ['5','6','7,8']}
55
+ # dest.deep_merge!(source, {:unpack_arrays => ','})
56
+ # Results: {:x => ['1','2','3','4','5','6','7','8'}
57
+ # Why: If receiving data from an HTML form, this makes it easy for a checkbox
58
+ # to pass multiple values from within a single HTML element
59
+ #
60
+ # There are many tests for this library - and you can learn more about the features
61
+ # and usages of deep_merge! by just browsing the test examples
62
+ def self.deep_merge!(source, dest, options = {})
63
+ # turn on this line for stdout debugging text
64
+ merge_debug = options[:merge_debug] || false
65
+ overwrite_unmergeable = !options[:preserve_unmergeables]
66
+ knockout_prefix = options[:knockout_prefix] || nil
67
+ raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!" if knockout_prefix == ""
68
+ raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!" if knockout_prefix && !overwrite_unmergeable
69
+ # if present: we will split and join arrays on this char before merging
70
+ array_split_char = options[:unpack_arrays] || false
71
+ # Don't merge but overwrite arrays
72
+ overwrite_arrays = options[:overwrite_arrays] || false
73
+ # request that we sort together any arrays when they are merged
74
+ sort_merged_arrays = options[:sort_merged_arrays] || false
75
+ di = options[:debug_indent] || ''
76
+ # do nothing if source is nil
77
+ return dest if source.nil? || (source.respond_to?(:blank?) && source.blank?)
78
+ # if dest doesn't exist, then simply copy source to it
79
+ if !(dest) && overwrite_unmergeable
80
+ dest = source; return dest
81
+ end
82
+
83
+ puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
84
+ if source.kind_of?(Hash)
85
+ puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
86
+ source.each do |src_key, src_value|
87
+ if dest.kind_of?(Hash)
88
+ puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
89
+ if dest[src_key]
90
+ puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
91
+ dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + ' '))
92
+ else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
93
+ puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
94
+ # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
95
+ begin
96
+ src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
97
+ rescue TypeError
98
+ src_dup = src_value
99
+ end
100
+ dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + ' '))
101
+ end
102
+ else # dest isn't a hash, so we overwrite it completely (if permitted)
103
+ if overwrite_unmergeable
104
+ puts "#{di} overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over-> #{dest.inspect}" if merge_debug
105
+ dest = overwrite_unmergeables(source, dest, options)
106
+ end
107
+ end
108
+ end
109
+ elsif source.kind_of?(Array)
110
+ puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
111
+ # if we are instructed, join/split any source arrays before processing
112
+ if array_split_char
113
+ puts "#{di} split/join on source: #{source.inspect}" if merge_debug
114
+ source = source.join(array_split_char).split(array_split_char)
115
+ if dest.kind_of?(Array)
116
+ dest = dest.join(array_split_char).split(array_split_char)
117
+ end
118
+ end
119
+ # if there's a naked knockout_prefix in source, that means we are to truncate dest
120
+ if source.index(knockout_prefix)
121
+ dest = clear_or_nil(dest); source.delete(knockout_prefix)
122
+ end
123
+ if dest.kind_of?(Array) and ! overwrite_arrays
124
+ if knockout_prefix
125
+ print "#{di} knocking out: " if merge_debug
126
+ # remove knockout prefix items from both source and dest
127
+ source.delete_if do |ko_item|
128
+ retval = false
129
+ item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
130
+ if item != ko_item
131
+ print "#{ko_item} - " if merge_debug
132
+ dest.delete(item)
133
+ dest.delete(ko_item)
134
+ retval = true
135
+ end
136
+ retval
137
+ end
138
+ puts if merge_debug
139
+ end
140
+ puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
141
+ dest = dest | source
142
+ dest.sort! if sort_merged_arrays
143
+ elsif overwrite_unmergeable or overwrite_arrays
144
+ puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
145
+ dest = overwrite_unmergeables(source, dest, options)
146
+ end
147
+ else # src_hash is not an array or hash, so we'll have to overwrite dest
148
+ puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
149
+ dest = overwrite_unmergeables(source, dest, options)
150
+ end
151
+ puts "#{di}Returning #{dest.inspect}" if merge_debug
152
+ dest
153
+ end # deep_merge!
154
+
155
+ # allows deep_merge! to uniformly handle overwriting of unmergeable entities
156
+ def self.overwrite_unmergeables(source, dest, options)
157
+ merge_debug = options[:merge_debug] || false
158
+ overwrite_unmergeable = !options[:preserve_unmergeables]
159
+ knockout_prefix = options[:knockout_prefix] || false
160
+ di = options[:debug_indent] || ''
161
+ if knockout_prefix && overwrite_unmergeable
162
+ if source.kind_of?(String) # remove knockout string from source before overwriting dest
163
+ if options[:overwrite_arrays] # Don't knock out strings for OATs
164
+ src_tmp = source
165
+ else
166
+ src_tmp = source.gsub(%r{^#{knockout_prefix}},"")
167
+ end
168
+ elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest
169
+ src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) }
170
+ else
171
+ src_tmp = source
172
+ end
173
+ if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest
174
+ puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug
175
+ dest = src_tmp
176
+ else # if we do find a knockout_prefix, then we just delete dest
177
+ puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug
178
+ dest = ""
179
+ end
180
+ elsif overwrite_unmergeable
181
+ dest = source
182
+ end
183
+ dest
184
+ end
185
+
186
+ def self.clear_or_nil(obj)
187
+ if obj.respond_to?(:clear)
188
+ obj.clear
189
+ else
190
+ obj = nil
191
+ end
192
+ obj
193
+ end
194
+
195
+ end # module DeepMerge
@@ -0,0 +1 @@
1
+ require 'deep_merge/deep_merge_hash'
@@ -0,0 +1,28 @@
1
+ require 'deep_merge/core'
2
+
3
+ module DeepMerge
4
+ module DeepMergeHash
5
+ # ko_hash_merge! will merge and knockout elements prefixed with DEFAULT_FIELD_KNOCKOUT_PREFIX
6
+ def ko_deep_merge!(source, options = {})
7
+ default_opts = {:knockout_prefix => "--", :preserve_unmergeables => false}
8
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
9
+ end
10
+
11
+ # deep_merge! will merge and overwrite any unmergeables in destination hash
12
+ def deep_merge!(source, options = {})
13
+ default_opts = {:preserve_unmergeables => false}
14
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
15
+ end
16
+
17
+ # deep_merge will merge and skip any unmergeables in destination hash
18
+ def deep_merge(source, options = {})
19
+ default_opts = {:preserve_unmergeables => true}
20
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
21
+ end
22
+
23
+ end # DeepMergeHashExt
24
+ end
25
+
26
+ class Hash
27
+ include DeepMerge::DeepMergeHash
28
+ end
@@ -0,0 +1,27 @@
1
+ require 'deep_merge/core'
2
+
3
+ module DeepMerge
4
+ module RailsCompat
5
+ # ko_hash_merge! will merge and knockout elements prefixed with DEFAULT_FIELD_KNOCKOUT_PREFIX
6
+ def ko_deeper_merge!(source, options = {})
7
+ default_opts = {:knockout_prefix => "--", :preserve_unmergeables => false}
8
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
9
+ end
10
+
11
+ # deep_merge! will merge and overwrite any unmergeables in destination hash
12
+ def deeper_merge!(source, options = {})
13
+ default_opts = {:preserve_unmergeables => false}
14
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
15
+ end
16
+
17
+ # deep_merge will merge and skip any unmergeables in destination hash
18
+ def deeper_merge(source, options = {})
19
+ default_opts = {:preserve_unmergeables => true}
20
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
21
+ end
22
+ end
23
+ end
24
+
25
+ class Hash
26
+ include ::DeepMerge::RailsCompat
27
+ end
@@ -0,0 +1,163 @@
1
+ require 'timeout'
2
+ require 'oats/ossh'
3
+ # Returns all the matching IPs from the listed logs
4
+
5
+ class ApplicationLogs
6
+
7
+ @@app_logs_error_getter = {} # webHostName => ApplicationLogs objects
8
+ @@ip = nil
9
+ @@plink_cmd_params = {} # webHostName => Extra parameters to connect or ''
10
+ PLINK_TIMEOUT = 5
11
+
12
+ # Call returns only errors occurring after the previous call.
13
+ def ApplicationLogs.new_errors(initial = false)
14
+ logs = $oats['env']['web']['logs']
15
+ logs = nil if logs.nil? or logs.empty?
16
+ return [] unless logs
17
+ host = $oats['env']['web']['host']
18
+ if @@app_logs_error_getter[host]
19
+ return [] if initial
20
+ else
21
+ @@app_logs_error_getter[host] = ApplicationLogs.new(host,logs)
22
+ end
23
+ return @@app_logs_error_getter[host].new_errors
24
+ end
25
+
26
+ def initialize(host,logs)
27
+ ApplicationLogs.set_ip unless @@ip
28
+ @logs = logs
29
+ @log_error_count = []
30
+ @command = "plink #{host} -l loguser sudo grep -i #{@@ip} " + @logs.join(' ')
31
+ ApplicationLogs.set_plink_cmd_params
32
+ @command_issue = @command
33
+ end
34
+
35
+ def new_errors
36
+ $log.debug "Interrogating the application logs: #{@command_issue}"
37
+ errors = IO.popen(@command).readlines
38
+ total_errors = 0
39
+ @log_error_count.each {|i| total_errors += i}
40
+ new_error = []
41
+ return new_error if total_errors == errors.length
42
+ i = 0
43
+ new_error_count = []
44
+ new_error_count[0] = 0
45
+ errors.each do |line|
46
+ prefix = Regexp.new('^'+@logs[i]+':')
47
+ unless prefix =~ line
48
+ @log_error_count[i] = new_error_count[i]
49
+ i += 1
50
+ break if i == @logs.length
51
+ new_error_count[i] = 0
52
+ redo
53
+ end
54
+ new_error_count[i] += 1
55
+ new_error << line if new_error_count[i] > (@log_error_count[i] ? @log_error_count[i] : 0)
56
+ end
57
+ @log_error_count[i] = new_error_count[i]
58
+ return new_error
59
+ end
60
+
61
+ # Tails logs continuously.
62
+ def ApplicationLogs.tail_errors
63
+ tail_ip = $oats['execution']['tail_logs_ip']
64
+ logs = $oats['env']['web']['logs']
65
+ logs = nil if logs.nil? or logs.empty?
66
+ host = $oats['env']['web']['host']
67
+ if tail_ip
68
+ raise(OatsBadInput, "The execution:tail_logs_ip is set to [#{tail_ip}] but env:web:logs is empty.") unless logs
69
+ else
70
+ return
71
+ end
72
+ if tail_ip and tail_ip.instance_of?(String)
73
+ if /^\d\d\.\d\d*\.\d\d*\.\d\d*$/ =~ tail_ip
74
+ @@ip = tail_ip
75
+ else
76
+ raise(OatsBadInput, "Input for execution:tail_logs_ip [#{tail_ip}] is not in proper IP format.")
77
+ end
78
+ else
79
+ ApplicationLogs.set_ip unless @@ip
80
+ end
81
+ ApplicationLogs.set_plink_cmd_params(true)
82
+ command = "plink #{host} -l loguser sudo tail -f " + logs.join(' ')
83
+ command_issue = command
84
+ puts "Filtering for [#{@@ip}] after executing command: #{command}"
85
+ IO.popen(command_issue) do |io|
86
+ while io.gets do
87
+ puts $_ if Regexp.new(@@ip) =~ $_ or /^==>/ =~ $_
88
+ end
89
+ end
90
+ exit 0 # Should never get here. User has to kill the process to quit
91
+ end
92
+
93
+ def ApplicationLogs.set_plink_cmd_params(from_tail = nil)
94
+ host = $oats['env']['web']['host']
95
+ return if @@plink_cmd_params[host]
96
+ # Ossh does not support this option anymore. Must go in via Paegant
97
+ # Clean-up the code below later.
98
+ @@plink_cmd_params = ''
99
+ error = 0
100
+ error_msg = nil
101
+ error_msg2 = nil
102
+ correct_response = false
103
+ cmd_issue = "plink #{host} -l loguser whoami 2>&1"
104
+ cmd_display = cmd_issue
105
+ $log.debug "Issuing: " + cmd_issue
106
+ $log.debug "Please start Paegant with loguser key if there is no response in {PLINK_TIMEOUT} seconds."
107
+ begin
108
+ timeout(PLINK_TIMEOUT) do
109
+ IO.popen(cmd_issue) do |ios|
110
+ while ios.gets(':') do
111
+ if /s password:/ =~ $_
112
+ error = 1
113
+ error_msg = "Received Plink authentication challenge from "
114
+ error_msg2 = "If you have not started Paegant already, please do so."
115
+ elsif /s password:/ =~ $_
116
+ error = 2
117
+ error_msg = "Received Plink authentication challenge from "
118
+ error_msg2 = "If you have not defined an entry for [#{host} on Putty already, please do so."
119
+ elsif /^Password:/ =~ $_
120
+ error = 3
121
+ error_msg = "Received 'sudo root' authentication challenge from "
122
+ error_msg2 = "Sudo password cash has timed out. Please type the following on a shell commandline: #{cmd_display}"
123
+ elsif /^Unable to open connection:/ =~ $_
124
+ error = 4
125
+ error_msg = "Could not connect to "
126
+ error_msg2 = "You need to unset error log interrogation to run this test in this environment."
127
+ # elsif /^root/ =~ $_
128
+ elsif /^loguser/ =~ $_
129
+ correct_response = true
130
+ end
131
+ $log.error $_ unless $_.nil? or correct_response
132
+ ios.gets
133
+ $log.error $_ unless $_.nil? or correct_response
134
+ end
135
+ end
136
+ end
137
+ rescue Timeout::Error
138
+ $log.error "plink command timed out after [#{PLINK_TIMEOUT}] seconds."
139
+ end
140
+ if error == 0 and correct_response
141
+ $log.info "Received proper response from Plink."
142
+ return
143
+ else
144
+ if error_msg
145
+ if error_msg2
146
+ $log.error error_msg + "[#{host}]"
147
+ else
148
+ raise(OatsSetupError,error_msg)
149
+ end
150
+ raise(OatsSetupError,error_msg2)
151
+ end
152
+ end
153
+ end
154
+
155
+ def ApplicationLogs.set_ip
156
+ IO.popen('ipconfig') do |io|
157
+ while io.gets do
158
+ @@ip = $_.chomp.sub(/.*IP Address.*: (\d.*\d).*/,'\1') if /IP Address.*: / =~ $_
159
+ end
160
+ end
161
+ end
162
+
163
+ end
@@ -0,0 +1,58 @@
1
+ # Should be overridden by the user if desired
2
+ module Oats
3
+
4
+ module BuildId
5
+ def BuildId.generate
6
+ return
7
+ dir_results = $oats['execution']['dir_results']
8
+ env_name = $oats['env']['name']
9
+ return unless env_name and $oats['execution']['build_version']
10
+ TestList.current.variations.last.env_name = env_name
11
+ run_info_file = File.join(dir_results,'run_info_' + env_name + '.txt')
12
+ unless File.exist?(run_info_file)
13
+ File.open(run_info_file, 'w') do |f|
14
+ YAML.dump($oats,f)
15
+ end
16
+ end
17
+ if Oats.context['build_version'] # Collected build data previously
18
+ return if Oats.context['build_version']['execution'] == $oats['execution']['build_version'] # no change
19
+ Oats.context['build_version']['execution'] = $oats['execution']['build_version'] # Use the latest, input from test list
20
+ return
21
+ end
22
+ # First time collecting build data
23
+ Oats.context['build_version'] = { 'execution' => $oats['execution']['build_version'] }
24
+ all_build_info = ''
25
+ build_id_file = File.join(dir_results,'buildID_' + env_name + '.txt')
26
+
27
+ for host in $oats['execution']['build_versions'] do
28
+ web_host = $oats['env'][host] && $oats['env'][host]['host']
29
+ next unless web_host
30
+ urls = $oats['env'][host]['buildID_url']
31
+ next unless urls
32
+ urls = [ urls ] unless urls.instance_of? Array
33
+ versions = ''
34
+ urls.each do |url|
35
+ begin
36
+ if RUBY_VERSION =~ /^1.9/
37
+ resp = Net::HTTP.new(web_host, 80).get(url) # 1.9 doesn't like the second parameter
38
+ else
39
+ resp = Net::HTTP.new(web_host, 80).get(url, nil )
40
+ end
41
+ build_info = resp.body if resp.code == '200'
42
+ rescue
43
+ $log.error $!.to_s
44
+ $log.error "Occurred after issuing get request to [http://#{web_host}#{url}]"
45
+ build_info = nil
46
+ end
47
+ if build_info
48
+ versions += ' ' unless versions == ''
49
+ versions += build_info[6..(build_info.index("\n")-1)]
50
+ all_build_info += "--- #{host} #{url} --- \n" + build_info + "\n"
51
+ end
52
+ end
53
+ Oats.context['build_version'][host] = versions
54
+ end if $oats['execution']['build_versions']
55
+ File.open(build_id_file, 'w') { |f| f.puts all_build_info } unless all_build_info == ''
56
+ end
57
+ end
58
+ end