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,128 @@
1
+ require 'optparse' # http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/index.html
2
+
3
+ module Oats
4
+
5
+ module CommandlineOptions
6
+
7
+ @@OPTIONS = nil
8
+ def CommandlineOptions.options(argv = nil)
9
+
10
+ # This should be set only once, coming from unit test or command-line
11
+ $oats_execution['input_args'] = $oats_unit_test ? $oats_unit_test['input_args'] : ARGV.dup
12
+
13
+ argv ||= $oats_execution['input_args'].dup
14
+ argv_save = argv.dup
15
+
16
+ begin
17
+
18
+ # Hold all of the options parsed from the command-line by OptionParser.
19
+ options = {}
20
+ optparse = OptionParser.new do|opts|
21
+ opts.banner = "Usage: oats.rb [options] test1 test2 ..."
22
+ opts.separator "Options:"
23
+ opts.on( '--tests t1,t2,t3', Array,
24
+ 'Test files for OATS execution.' ) do |t|
25
+ options['execution:test_files'] = t
26
+ end
27
+ opts.on( '-b', '--browser_type TYPE', ['firefox', 'iexplore','chrome'],
28
+ 'Select test execution browser type (firefox, iexplore, chrome)' ) do |t|
29
+ options['selenium:browser_type'] = t
30
+ end
31
+ opts.on( '-e', '--environments env1,env2,env3', Array,
32
+ 'Environment list for OATS execution.' ) do |t|
33
+ options['execution:environments'] = t
34
+ end
35
+ opts.on( '-t', '--test_dir DIR_TESTS',
36
+ 'Test directory to override environment variable OATS_TESTS.' ) do |t|
37
+ options['_:dir_tests'] = t
38
+ end
39
+ opts.on( '-i', '--ini INI_YAML_FILE',
40
+ 'The oats-user.yml to use.' ) do |t|
41
+ options['_:ini_file'] = t
42
+ end
43
+ opts.on( '-p', '--port PORT', Integer,
44
+ 'Port number for the Oats Agent.' ) do |t|
45
+ options['execution:occ:agent_port'] = t if t
46
+ end
47
+ opts.on( '-n', '--nickname NICKNAME',
48
+ 'Nickname to display on OCC for the Oats Agent.' ) do |t|
49
+ options['execution:occ:agent_nickname'] = t if t
50
+ end
51
+ opts.on( '-o', '--options key11.key12.key13:val1,key21.key22:val2,...', Array,
52
+ 'Options to override values specified in oats.yml as well as other commandline options.' ) do |t|
53
+ options['_:options'] = t
54
+ end
55
+ opts.on( '-j', '--json JSON',
56
+ 'The json hash to merge with oats data.' ) do |t|
57
+ options['_:json'] = t
58
+ end
59
+ opts.on( '-q', '--quiet',
60
+ 'Do not echo anything to the console while running.' ) do |t|
61
+ options['_:quiet'] = true
62
+ end
63
+
64
+ opts.on( '-a', '--agent',
65
+ 'Invokes background agent handling.' ) do |t|
66
+ options['_:agent'] = true
67
+ end
68
+ opts.on( '-u', '--oats_user OATS_USER',
69
+ 'Sets OATS_USER for agent, in conjunction with -a.' ) do |t|
70
+ options['_:oats_user'] = t
71
+ end
72
+ opts.on( '-k', '--kill_agent',
73
+ 'Kill the agent.' ) do |t|
74
+ options['_:kill_agent, in conjunction with -a'] = true
75
+ end
76
+
77
+
78
+ # Development options
79
+ opts.on( '-g', '--gemfile GEMFILE',
80
+ 'Gemfile path to be included.' ) do |t|
81
+ options['_:gemfile'] = t
82
+ end
83
+ opts.on( '-d' , '--d_options unit_test_dir1,unit_test_dir2', Array,
84
+ 'NetBeans passes these d options to TestUnit.' ) do |t|
85
+ options['_:d_options'] = t
86
+ end
87
+ # opts.on( '-s', '--show_result_ide TYPE', [ '0', '1', '2'],
88
+ # 'Select the trigger level to show TestRunner results (0, 1, 2) for (On failure, Never, Always)' ) do |t|
89
+ # options['execution:ide:show_result'] = t.to_f
90
+ # end
91
+ # opts.on( '--log_level_console LEVEL',["DEBUG", "INFO", "WARN", "ERROR", "FATAL"],
92
+ # 'Select logging level ("DEBUG", "INFO", "WARN", "ERROR", "FATAL")' ) do |t|
93
+ # options['execution:log_level_console'] = t
94
+ # end
95
+ # opts.on( '-t', '--tail_logs_ip [HOSTIP]',
96
+ # 'Tail the application logs for errors. Just input YES for the host IP executing OATS.' ) do |t|
97
+ # t = true unless t
98
+ # options['execution:tail_logs_ip'] = t
99
+ # end
100
+ # opts.on( '-r', '--restrict t1,t2,t3,...', Array,
101
+ # 'Restrict test list execution to the listed tests. NOT FULLY IMPLEMENTED YET.' ) do |t|
102
+ # options['execution:restrict_tests'] = t
103
+ # end
104
+ # opts.on( '-c', '--command COMMAND_STRING',
105
+ # 'Command issued by the client.' ) do |t|
106
+ # options['_:command'] = t
107
+ # end
108
+ opts.on_tail( '-h', '--help', 'Display this screen' ) { $stderr.puts opts; exit }
109
+ end
110
+
111
+ optparse.parse!(argv)
112
+ if argv and ! argv.empty?
113
+ options['execution:test_files'] ||= []
114
+ options['execution:test_files'] += argv
115
+ end
116
+
117
+ rescue Exception => e
118
+ raise unless e.class.to_s =~ /^OptionParser::/
119
+ $stderr.puts e.message
120
+ $stderr.puts "Please type 'oats -h' for valid options."
121
+ exit 1
122
+ end
123
+ options['_:args'] = argv_save
124
+ @@OPTIONS = options
125
+ end
126
+
127
+ end
128
+ end
data/lib/oats/diff.rb ADDED
@@ -0,0 +1,278 @@
1
+ class Diff
2
+
3
+ def Diff.lcs(a, b)
4
+ astart = 0
5
+ bstart = 0
6
+ afinish = a.length-1
7
+ bfinish = b.length-1
8
+ mvector = []
9
+
10
+ # First we prune off any common elements at the beginning
11
+ while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
12
+ mvector[astart] = bstart
13
+ astart += 1
14
+ bstart += 1
15
+ end
16
+
17
+ # now the end
18
+ while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
19
+ mvector[afinish] = bfinish
20
+ afinish -= 1
21
+ bfinish -= 1
22
+ end
23
+
24
+ bmatches = b.reverse_hash(bstart..bfinish)
25
+ thresh = []
26
+ links = []
27
+
28
+ (astart..afinish).each { |aindex|
29
+ aelem = a[aindex]
30
+ next unless bmatches.has_key? aelem
31
+ k = nil
32
+ bmatches[aelem].reverse.each { |bindex|
33
+ if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
34
+ thresh[k] = bindex
35
+ else
36
+ k = thresh.replacenextlarger(bindex, k)
37
+ end
38
+ links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
39
+ }
40
+ }
41
+
42
+ if !thresh.empty?
43
+ link = links[thresh.length-1]
44
+ while link
45
+ mvector[link[1]] = link[2]
46
+ link = link[0]
47
+ end
48
+ end
49
+
50
+ return mvector
51
+ end
52
+
53
+ def makediff(a, b)
54
+ mvector = Diff.lcs(a, b)
55
+ ai = bi = 0
56
+ while ai < mvector.length
57
+ bline = mvector[ai]
58
+ if bline
59
+ while bi < bline
60
+ discardb(bi, b[bi])
61
+ bi += 1
62
+ end
63
+ match(ai, bi)
64
+ bi += 1
65
+ else
66
+ discarda(ai, a[ai])
67
+ end
68
+ ai += 1
69
+ end
70
+ while ai < a.length
71
+ discarda(ai, a[ai])
72
+ ai += 1
73
+ end
74
+ while bi < b.length
75
+ discardb(bi, b[bi])
76
+ bi += 1
77
+ end
78
+ match(ai, bi)
79
+ 1
80
+ end
81
+
82
+ def compactdiffs
83
+ diffs = []
84
+ @diffs.each { |df|
85
+ i = 0
86
+ curdiff = []
87
+ while i < df.length
88
+ whot = df[i][0]
89
+ s = @isstring ? df[i][2].chr : [df[i][2]]
90
+ p = df[i][1]
91
+ last = df[i][1]
92
+ i += 1
93
+ while df[i] && df[i][0] == whot && df[i][1] == last+1
94
+ s << df[i][2]
95
+ last = df[i][1]
96
+ i += 1
97
+ end
98
+ curdiff.push [whot, p, s]
99
+ end
100
+ diffs.push curdiff
101
+ }
102
+ return diffs
103
+ end
104
+
105
+ attr_reader :diffs, :difftype
106
+
107
+ def initialize(diffs_or_a, b = nil, isstring = nil)
108
+ if b.nil?
109
+ @diffs = diffs_or_a
110
+ @isstring = isstring
111
+ else
112
+ @diffs = []
113
+ @curdiffs = []
114
+ makediff(diffs_or_a, b)
115
+ @difftype = diffs_or_a.class
116
+ end
117
+ end
118
+
119
+ def match(ai, bi)
120
+ @diffs.push @curdiffs unless @curdiffs.empty?
121
+ @curdiffs = []
122
+ end
123
+
124
+ def discarda(i, elem)
125
+ @curdiffs.push ['-', i, elem]
126
+ end
127
+
128
+ def discardb(i, elem)
129
+ @curdiffs.push ['+', i, elem]
130
+ end
131
+
132
+ def compact
133
+ return Diff.new(compactdiffs)
134
+ end
135
+
136
+ def compact!
137
+ @diffs = compactdiffs
138
+ end
139
+
140
+ def inspect
141
+ @diffs.inspect
142
+ end
143
+
144
+ end
145
+
146
+ module Diffable
147
+ def diff(b)
148
+ Diff.new(self, b)
149
+ end
150
+
151
+ # Create a hash that maps elements of the array to arrays of indices
152
+ # where the elements are found.
153
+
154
+ def reverse_hash(range = (0...self.length))
155
+ revmap = {}
156
+ range.each { |i|
157
+ elem = self[i]
158
+ if revmap.has_key? elem
159
+ revmap[elem].push i
160
+ else
161
+ revmap[elem] = [i]
162
+ end
163
+ }
164
+ return revmap
165
+ end
166
+
167
+ def replacenextlarger(value, high = nil)
168
+ high ||= self.length
169
+ if self.empty? || value > self[-1]
170
+ push value
171
+ return high
172
+ end
173
+ # binary search for replacement point
174
+ low = 0
175
+ while low < high
176
+ index = (high+low)/2
177
+ found = self[index]
178
+ return nil if value == found
179
+ if value > found
180
+ low = index + 1
181
+ else
182
+ high = index
183
+ end
184
+ end
185
+
186
+ self[low] = value
187
+ # $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n"
188
+ # $stderr.puts self.inspect
189
+ #gets
190
+ #p length - low
191
+ return low
192
+ end
193
+
194
+ def patch(diff)
195
+ newary = nil
196
+ if diff.difftype == String
197
+ newary = diff.difftype.new('')
198
+ else
199
+ newary = diff.difftype.new
200
+ end
201
+ ai = 0
202
+ bi = 0
203
+ diff.diffs.each { |d|
204
+ d.each { |mod|
205
+ case mod[0]
206
+ when '-'
207
+ while ai < mod[1]
208
+ newary << self[ai]
209
+ ai += 1
210
+ bi += 1
211
+ end
212
+ ai += 1
213
+ when '+'
214
+ while bi < mod[1]
215
+ newary << self[ai]
216
+ ai += 1
217
+ bi += 1
218
+ end
219
+ newary << mod[2]
220
+ bi += 1
221
+ else
222
+ raise "Unknown diff action"
223
+ end
224
+ }
225
+ }
226
+ while ai < self.length
227
+ newary << self[ai]
228
+ ai += 1
229
+ bi += 1
230
+ end
231
+ return newary
232
+ end
233
+ end
234
+
235
+ class Array
236
+ include Diffable
237
+ end
238
+
239
+ class String
240
+ include Diffable
241
+ end
242
+
243
+ =begin
244
+ = Diff
245
+ (({diff.rb})) - computes the differences between two arrays or
246
+ strings. Copyright (C) 2001 Lars Christensen
247
+
248
+ == Synopsis
249
+
250
+ diff = Diff.new(a, b)
251
+ b = a.patch(diff)
252
+
253
+ == Class Diff
254
+ === Class Methods
255
+ --- Diff.new(a, b)
256
+ --- a.diff(b)
257
+ Creates a Diff object which represent the differences between
258
+ ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
259
+ of any objects, strings, or object of any class that include
260
+ module ((|Diffable|))
261
+
262
+ == Module Diffable
263
+ The module ((|Diffable|)) is intended to be included in any class for
264
+ which differences are to be computed. Diffable is included into String
265
+ and Array when (({diff.rb})) is (({require}))'d.
266
+
267
+ Classes including Diffable should implement (({[]})) to get element at
268
+ integer indices, (({<<})) to append elements to the object and
269
+ (({ClassName#new})) should accept 0 arguments to create a new empty
270
+ object.
271
+
272
+ === Instance Methods
273
+ --- Diffable#patch(diff)
274
+ Applies the differences from ((|diff|)) to the object ((|obj|))
275
+ and return the result. ((|obj|)) is not changed. ((|obj|)) and
276
+ can be either an array or a string, but must match the object
277
+ from which the ((|diff|)) was created.
278
+ =end