uttk 0.3.1.2

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 (276) hide show
  1. data/AUTHORS +36 -0
  2. data/COPYING +18 -0
  3. data/ChangeLog +7673 -0
  4. data/GUIDELINES +86 -0
  5. data/LGPL +504 -0
  6. data/NEWS +158 -0
  7. data/NORM +137 -0
  8. data/README +180 -0
  9. data/Rakefile +8 -0
  10. data/SPEC.gemspec +15 -0
  11. data/SPEC.yml +60 -0
  12. data/TODO +23 -0
  13. data/TODO.old +31 -0
  14. data/VERSION +5 -0
  15. data/bin/getopts/uttk.rb +390 -0
  16. data/bin/uttk +188 -0
  17. data/bin/uttk-unit +125 -0
  18. data/lib/uttk.rb +288 -0
  19. data/lib/uttk/dumpers/Basic.rb +23 -0
  20. data/lib/uttk/dumpers/BasicColor.rb +35 -0
  21. data/lib/uttk/dumpers/Dumper.rb +77 -0
  22. data/lib/uttk/dumpers/Html.rb +271 -0
  23. data/lib/uttk/dumpers/Path.rb +24 -0
  24. data/lib/uttk/dumpers/Xml.rb +88 -0
  25. data/lib/uttk/dumpers/Yaml.rb +138 -0
  26. data/lib/uttk/filters.rb +128 -0
  27. data/lib/uttk/filters/Buffer.rb +119 -0
  28. data/lib/uttk/filters/Compact.rb +75 -0
  29. data/lib/uttk/filters/Default.rb +27 -0
  30. data/lib/uttk/filters/DefaultColor.rb +27 -0
  31. data/lib/uttk/filters/Filter.rb +53 -0
  32. data/lib/uttk/filters/Id.rb +30 -0
  33. data/lib/uttk/filters/JustStatus.rb +25 -0
  34. data/lib/uttk/filters/KeepSkipBased.rb +38 -0
  35. data/lib/uttk/filters/NodeCut.rb +97 -0
  36. data/lib/uttk/filters/RPathFilter.rb +134 -0
  37. data/lib/uttk/filters/Saver.rb +53 -0
  38. data/lib/uttk/filters/TextFilter.rb +69 -0
  39. data/lib/uttk/generators/dumper_generator.rb +28 -0
  40. data/lib/uttk/generators/filter_generator.rb +28 -0
  41. data/lib/uttk/generators/generator.rb +86 -0
  42. data/lib/uttk/generators/generator_generator.rb +26 -0
  43. data/lib/uttk/generators/loader_generator.rb +28 -0
  44. data/lib/uttk/generators/path_filter_generator.rb +28 -0
  45. data/lib/uttk/generators/strategy_generator.rb +28 -0
  46. data/lib/uttk/generators/templates/dumper.rb +50 -0
  47. data/lib/uttk/generators/templates/filter.rb +50 -0
  48. data/lib/uttk/generators/templates/generator.rb +28 -0
  49. data/lib/uttk/generators/templates/loader.rb +26 -0
  50. data/lib/uttk/generators/templates/path_filter.rb +28 -0
  51. data/lib/uttk/generators/templates/strategy.rb +59 -0
  52. data/lib/uttk/generators/templates/strategy.yml +28 -0
  53. data/lib/uttk/generators/templates/unit_test.rb +46 -0
  54. data/lib/uttk/loaders/Loader.rb +180 -0
  55. data/lib/uttk/loaders/Ruby.rb +28 -0
  56. data/lib/uttk/loaders/Yaml.rb +98 -0
  57. data/lib/uttk/logger.rb +306 -0
  58. data/lib/uttk/logger/backend.rb +170 -0
  59. data/lib/uttk/logger/path.rb +202 -0
  60. data/lib/uttk/logger/section_node.rb +214 -0
  61. data/lib/uttk/logger/severity.rb +63 -0
  62. data/lib/uttk/logger/to_uttk_log.rb +127 -0
  63. data/lib/uttk/logger/verbosity.rb +61 -0
  64. data/lib/uttk/logger_factory.rb +55 -0
  65. data/lib/uttk/path_filters/ColorStatus.rb +57 -0
  66. data/lib/uttk/path_filters/PathFilter.rb +27 -0
  67. data/lib/uttk/path_filters/RemoveTypes.rb +25 -0
  68. data/lib/uttk/status.rb +146 -0
  69. data/lib/uttk/strategies/Abort.rb +24 -0
  70. data/lib/uttk/strategies/Assert.rb +44 -0
  71. data/lib/uttk/strategies/Authors.rb +45 -0
  72. data/lib/uttk/strategies/Block.rb +113 -0
  73. data/lib/uttk/strategies/Bootstrap.rb +55 -0
  74. data/lib/uttk/strategies/Checkout.rb +64 -0
  75. data/lib/uttk/strategies/Clean.rb +29 -0
  76. data/lib/uttk/strategies/Cmd.rb +60 -0
  77. data/lib/uttk/strategies/CmdBase.rb +130 -0
  78. data/lib/uttk/strategies/Collection.rb +158 -0
  79. data/lib/uttk/strategies/Compile.rb +59 -0
  80. data/lib/uttk/strategies/Composite.rb +201 -0
  81. data/lib/uttk/strategies/Composite/contents_eval.rb +40 -0
  82. data/lib/uttk/strategies/Configure.rb +66 -0
  83. data/lib/uttk/strategies/Error.rb +23 -0
  84. data/lib/uttk/strategies/Fail.rb +26 -0
  85. data/lib/uttk/strategies/IOBased.rb +159 -0
  86. data/lib/uttk/strategies/Import.rb +60 -0
  87. data/lib/uttk/strategies/Iterate.rb +139 -0
  88. data/lib/uttk/strategies/JUnit.rb +205 -0
  89. data/lib/uttk/strategies/KillAll.rb +62 -0
  90. data/lib/uttk/strategies/Make.rb +94 -0
  91. data/lib/uttk/strategies/Package.rb +129 -0
  92. data/lib/uttk/strategies/PackageCollection.rb +78 -0
  93. data/lib/uttk/strategies/Pass.rb +24 -0
  94. data/lib/uttk/strategies/Pool.rb +104 -0
  95. data/lib/uttk/strategies/ProbabilityThreshold.rb +46 -0
  96. data/lib/uttk/strategies/Proxy.rb +42 -0
  97. data/lib/uttk/strategies/RMatch.rb +92 -0
  98. data/lib/uttk/strategies/RUnit.rb +132 -0
  99. data/lib/uttk/strategies/SignalCmd.rb +85 -0
  100. data/lib/uttk/strategies/Sleep.rb +36 -0
  101. data/lib/uttk/strategies/SqlQuery.rb +120 -0
  102. data/lib/uttk/strategies/Strategy.rb +683 -0
  103. data/lib/uttk/strategies/Stub.rb +37 -0
  104. data/lib/uttk/strategies/SubCmd.rb +77 -0
  105. data/lib/uttk/strategies/Suite.rb +71 -0
  106. data/lib/uttk/strategies/Test.rb +89 -0
  107. data/lib/uttk/streams.rb +69 -0
  108. data/lib/uttk/streams/Diff.rb +60 -0
  109. data/lib/uttk/streams/HexaDiff.rb +35 -0
  110. data/lib/uttk/streams/Stream.rb +76 -0
  111. data/lib/uttk/weights.rb +17 -0
  112. data/lib/uttk/weights/WExpr.rb +68 -0
  113. data/lib/uttk/weights/WFloat.rb +23 -0
  114. data/lib/uttk/weights/WMin.rb +22 -0
  115. data/lib/uttk/weights/Weight.rb +105 -0
  116. data/lib/www/javascripts/uttk.js +185 -0
  117. data/misc/expandtab.rb +29 -0
  118. data/misc/header.rb +44 -0
  119. data/misc/renaming +57 -0
  120. data/misc/textile_compiler +194 -0
  121. data/misc/uttk-grep.sh +8 -0
  122. data/misc/uttk-line-count.rb +143 -0
  123. data/test/examples-suite.yml +8 -0
  124. data/test/examples/README +68 -0
  125. data/test/examples/basic.rb +10 -0
  126. data/test/examples/basic.yml +9 -0
  127. data/test/examples/cache/cache_and_fatal.yml +5 -0
  128. data/test/examples/cache/simple.yml +30 -0
  129. data/test/examples/sql/basic.yml +24 -0
  130. data/test/examples/students-suite.yml +9 -0
  131. data/test/examples/students/ball.yml +11 -0
  132. data/test/examples/students/glob_stud.yml +20 -0
  133. data/test/examples/students/mini-lib.yml +61 -0
  134. data/test/examples/students/pool_stud.yml +31 -0
  135. data/test/examples/students/stud.yml +21 -0
  136. data/test/fixtures/ball/20040804-exam_a1-zapngo-tessar_m.tar.gz +0 -0
  137. data/test/fixtures/ball/Makefile +24 -0
  138. data/test/fixtures/ball/bar_p-mini-lib.tar.bz2 +0 -0
  139. data/test/fixtures/ball/bar_p-mini-lib/Makefile +20 -0
  140. data/test/fixtures/ball/bar_p-mini-lib/my_strlen.c +13 -0
  141. data/test/fixtures/ball/foo_s-mini-lib.tar.bz2 +0 -0
  142. data/test/fixtures/ball/foo_s-mini-lib/Makefile +20 -0
  143. data/test/fixtures/ball/foo_s-mini-lib/configure +2 -0
  144. data/test/fixtures/ball/foo_s-mini-lib/my_strlen.c +10 -0
  145. data/test/fixtures/ball/hello.tar.bz2 +0 -0
  146. data/test/fixtures/ball/hello.tar.gz +0 -0
  147. data/test/fixtures/ball/hello/Makefile +14 -0
  148. data/test/fixtures/ball/hello/hello.c +7 -0
  149. data/test/fixtures/ball/jack-exit.tar.bz2 +0 -0
  150. data/test/fixtures/ball/jack-exit/Makefile +14 -0
  151. data/test/fixtures/ball/jack-exit/exit.c +16 -0
  152. data/test/fixtures/ball/joe-exit.tar.bz2 +0 -0
  153. data/test/fixtures/ball/joe-exit/Makefile +14 -0
  154. data/test/fixtures/ball/joe-exit/exit.c +8 -0
  155. data/test/fixtures/ball/joe_i-mini-lib.tar.bz2 +0 -0
  156. data/test/fixtures/ball/joe_i-mini-lib/Makefile +20 -0
  157. data/test/fixtures/ball/joe_i-mini-lib/configure +2 -0
  158. data/test/fixtures/ball/joe_i-mini-lib/my_strlen.c +10 -0
  159. data/test/fixtures/ball/john-exit.tar.bz2 +0 -0
  160. data/test/fixtures/ball/john-exit/Makefile +14 -0
  161. data/test/fixtures/ball/john-exit/exit.c +6 -0
  162. data/test/fixtures/ball/qux_j-mini-lib.tar.bz2 +0 -0
  163. data/test/fixtures/ball/qux_j-mini-lib/Makefile +20 -0
  164. data/test/fixtures/ball/qux_j-mini-lib/my_strlen.c +12 -0
  165. data/test/fixtures/binaries/segv +0 -0
  166. data/test/fixtures/binaries/segv.c +10 -0
  167. data/test/fixtures/binaries/segv.rb +2 -0
  168. data/test/fixtures/demo/command-tutorial/steps/1/check.yml +5 -0
  169. data/test/fixtures/demo/command-tutorial/steps/1/pluralizer.rb +10 -0
  170. data/test/fixtures/demo/command-tutorial/steps/2/bad_check.yml +7 -0
  171. data/test/fixtures/demo/command-tutorial/steps/2/check.yml +7 -0
  172. data/test/fixtures/demo/command-tutorial/steps/2/pluralizer.rb +10 -0
  173. data/test/fixtures/demo/command-tutorial/steps/3.1/check.yml +12 -0
  174. data/test/fixtures/demo/command-tutorial/steps/3/check.yml +14 -0
  175. data/test/fixtures/demo/command-tutorial/steps/4.1/bird.txt +1 -0
  176. data/test/fixtures/demo/command-tutorial/steps/4.1/check.yml +12 -0
  177. data/test/fixtures/demo/command-tutorial/steps/4/check.yml +12 -0
  178. data/test/fixtures/demo/command-tutorial/steps/4/pluralizer.rb +12 -0
  179. data/test/fixtures/demo/command-tutorial/steps/5.1/bird.txt +1 -0
  180. data/test/fixtures/demo/command-tutorial/steps/5.1/check.yml +17 -0
  181. data/test/fixtures/demo/command-tutorial/steps/5.1/pluralizer.rb +17 -0
  182. data/test/fixtures/demo/command-tutorial/steps/5/bird.txt +1 -0
  183. data/test/fixtures/demo/command-tutorial/steps/5/check.yml +16 -0
  184. data/test/fixtures/demo/command-tutorial/steps/5/pluralizer.rb +16 -0
  185. data/test/fixtures/demo/command-tutorial/steps/6.1/bird.txt +1 -0
  186. data/test/fixtures/demo/command-tutorial/steps/6.1/check.yml +22 -0
  187. data/test/fixtures/demo/command-tutorial/steps/6.1/pluralizer.rb +17 -0
  188. data/test/fixtures/demo/command-tutorial/steps/6/bird.txt +1 -0
  189. data/test/fixtures/demo/command-tutorial/steps/6/check.yml +21 -0
  190. data/test/fixtures/demo/command-tutorial/steps/6/pluralizer.rb +17 -0
  191. data/test/fixtures/demo/command-tutorial/steps/7/bird.txt +1 -0
  192. data/test/fixtures/demo/command-tutorial/steps/7/check.yml +22 -0
  193. data/test/fixtures/demo/command-tutorial/steps/7/pluralizer.rb +17 -0
  194. data/test/fixtures/demo/filter-tutorial/check.yml +20 -0
  195. data/test/fixtures/demo/filter-tutorial/filters/CutSkip100.rb +19 -0
  196. data/test/fixtures/demo/filter-tutorial/pluralizer.rb +17 -0
  197. data/test/fixtures/java/unit/MultiRight/Foo/Foo.java +11 -0
  198. data/test/fixtures/java/unit/MultiRight/Foo/FooTest.java +15 -0
  199. data/test/fixtures/java/unit/MultiRight/MultiRight.java +13 -0
  200. data/test/fixtures/java/unit/MultiRight/MultiRightTest.java +12 -0
  201. data/test/fixtures/java/unit/MultiRight/bar/Bar.java +11 -0
  202. data/test/fixtures/java/unit/MultiRight/bar/BarTest.java +21 -0
  203. data/test/fixtures/java/unit/MultiRight/build.sh +7 -0
  204. data/test/fixtures/java/unit/SimpleException/SimpleExceptionTest.java +11 -0
  205. data/test/fixtures/java/unit/SimpleException/build.sh +4 -0
  206. data/test/fixtures/java/unit/build.sh +9 -0
  207. data/test/fixtures/java/unit/multibar.yml +6 -0
  208. data/test/fixtures/java/unit/multifoo.yml +6 -0
  209. data/test/fixtures/java/unit/multiright.yml +8 -0
  210. data/test/fixtures/java/unit/simple_exception.yml +6 -0
  211. data/test/fixtures/mini-lib/Makefile +9 -0
  212. data/test/fixtures/mini-lib/strlen.c +15 -0
  213. data/test/fixtures/package/pkg_foo.tar.gz +0 -0
  214. data/test/fixtures/package/pkg_foo/Makefile +20 -0
  215. data/test/fixtures/package/pkg_foo/bootstrap +3 -0
  216. data/test/fixtures/package/pkg_foo/configure +3 -0
  217. data/test/fixtures/package/pkg_foo/foo.sh +2 -0
  218. data/test/fixtures/text/1.txt +4 -0
  219. data/test/fixtures/unit/bad.rb +26 -0
  220. data/test/fixtures/unit/error.rb +6 -0
  221. data/test/fixtures/unit/good.rb +26 -0
  222. data/test/functional-suite.yml +10 -0
  223. data/test/functional/author.yml +11 -0
  224. data/test/functional/base.yml +119 -0
  225. data/test/functional/base_pool.yml +13 -0
  226. data/test/functional/block.yml +13 -0
  227. data/test/functional/cat.yml +16 -0
  228. data/test/functional/cmd.yml +17 -0
  229. data/test/functional/diff.yml +27 -0
  230. data/test/functional/env_cmd.yml +53 -0
  231. data/test/functional/exit.yml +15 -0
  232. data/test/functional/fatal.yml +23 -0
  233. data/test/functional/glob.yml +11 -0
  234. data/test/functional/hexa-diff.yml +25 -0
  235. data/test/functional/import.yml +41 -0
  236. data/test/functional/iterate.yml +99 -0
  237. data/test/functional/killall.yml +31 -0
  238. data/test/functional/pkg.yml +14 -0
  239. data/test/functional/probability_threshold.yml +35 -0
  240. data/test/functional/r_unit.yml +26 -0
  241. data/test/functional/rmatch.yml +122 -0
  242. data/test/functional/signal_cmd.yml +22 -0
  243. data/test/functional/sub.yml +15 -0
  244. data/test/functional/test.yml +25 -0
  245. data/test/functional/timeout.yml +20 -0
  246. data/test/functional/wc.yml +26 -0
  247. data/test/functional/weight.yml +152 -0
  248. data/test/pkg-suite.yml +8 -0
  249. data/test/pkg/cmdline.yml +80 -0
  250. data/test/pool-suite.yml +8 -0
  251. data/test/pool/base.yml +12 -0
  252. data/test/pool/pool.yml +25 -0
  253. data/test/ruby-suite.rb +10 -0
  254. data/test/ruby-suite.yml +5 -0
  255. data/test/ruby/base.rb +119 -0
  256. data/test/ruby/iterate.rb +21 -0
  257. data/test/ruby/wc.rb +43 -0
  258. data/test/unit-suite.yml +10 -0
  259. data/test/unit/dumpers/path_test.rb +46 -0
  260. data/test/unit/dumpers/xml_test.rb +65 -0
  261. data/test/unit/dumpers/yaml_test.rb +65 -0
  262. data/test/unit/filters/buffer_test.rb +168 -0
  263. data/test/unit/filters/keep_skip_based_test.rb +46 -0
  264. data/test/unit/filters/node_cut_test.rb +72 -0
  265. data/test/unit/filters/rpath_filter_test.rb +191 -0
  266. data/test/unit/filters/text_filter_test.rb +46 -0
  267. data/test/unit/filters_test.rb +119 -0
  268. data/test/unit/logger/section_node_test.rb +120 -0
  269. data/test/unit/logger/severity_test.rb +37 -0
  270. data/test/unit/logger/to_uttk_log_test.rb +113 -0
  271. data/test/unit/logger/verbosity_test.rb +44 -0
  272. data/test/unit/logger_test.rb +203 -0
  273. data/test/unit/strategies/suite_test.rb +151 -0
  274. data/test/uttk-check.yml +8 -0
  275. data/test/uttk-distcheck.yml +18 -0
  276. metadata +399 -0
@@ -0,0 +1,85 @@
1
+ # Author:: Vincent CUISSARD <cuissa_v@epita.fr>.
2
+ # Copyright:: Copyright (c) 2005 Uttk Team. All rights reserved.
3
+ # License:: LGPL
4
+ # $Id: /fey/uttk/trunk/lib/uttk/strategies/SignalCmd.rb 8789 2005-09-27T14:49:49.088376Z ertai $
5
+
6
+
7
+ module Uttk
8
+
9
+ module Strategies
10
+
11
+ class SignalCmd < Cmd
12
+ include Concrete
13
+
14
+ @@signal_names = nil
15
+
16
+ #
17
+ # Methods
18
+ #
19
+
20
+ def run_impl
21
+ super
22
+
23
+ # Check if command has exited normaly
24
+ case
25
+ when @my_status.exited?
26
+ # Process run successfully
27
+ @my_signaled = false
28
+ when @my_status.signaled?
29
+ # Process was signaled
30
+ @my_signaled = true
31
+ @my_exit = 128 + @my_status.termsig
32
+ else
33
+ # Problem on process
34
+ fail('process may be ill')
35
+ end
36
+ end
37
+ protected :run_impl
38
+
39
+
40
+ def assertion
41
+ case
42
+ when (@my_signaled and not @signaled)
43
+ fail("command was signaled by #{SignalCmd.signal_name(@my_exit)}")
44
+ when (not @my_signaled and @signaled)
45
+ fail("command wasn't signaled by #@signal")
46
+ when (@my_signaled == @signaled and @signaled)
47
+ sig_name = SignalCmd.signal_name(@my_exit)
48
+ unless sig_name == signal
49
+ err = "command signaled by #{sig_name}, "
50
+ err << "must be signaled by #@signal"
51
+ fail(err)
52
+ end
53
+ end
54
+ super
55
+ end
56
+ protected :assertion
57
+
58
+ def SignalCmd.signal_name ( status )
59
+ signal = status - 128
60
+ if @@signal_names.nil?
61
+ @@signal_names = { }
62
+ Signal.list.each do |key, value|
63
+ @@signal_names[value] = key
64
+ end
65
+ end
66
+ @@signal_names[signal]
67
+ end
68
+
69
+ def signal= ( signal_name )
70
+ @signal = signal_name
71
+ @signaled = true
72
+ end
73
+
74
+ #
75
+ # Attributes
76
+ #
77
+
78
+ attribute :signal, 'the signal name', nil
79
+ attribute :signaled, 'process must be signaled', false
80
+
81
+ end # class SignalCmd
82
+
83
+ end # module Strategies
84
+
85
+ end # module Uttk
@@ -0,0 +1,36 @@
1
+ # Author:: Nicolas Despres <nicolas.despres@gmail.com>.
2
+ # Copyright:: Copyright (c) 2004, 2005 Uttk team. All rights reserved.
3
+ # License:: LGPL
4
+ # $Id: /fey/uttk/trunk/lib/uttk/strategies/Sleep.rb 8789 2005-09-27T14:49:49.088376Z ertai $
5
+
6
+
7
+ module Uttk
8
+
9
+ module Strategies
10
+
11
+ # A test strategy class that only sleep for a moment before to pass.
12
+ class Sleep < Strategy
13
+ include Concrete
14
+
15
+ def delay=(other)
16
+ other = other.to_f
17
+ if other >= 0
18
+ @delay = other
19
+ else
20
+ raise(ArgumentError, "`#{other}' - sleep delay must be >= 0")
21
+ end
22
+ end
23
+
24
+ protected
25
+ def run_impl
26
+ sleep(@delay)
27
+ pass
28
+ end
29
+
30
+ attribute :delay, 'Delay in second to sleep', 0
31
+
32
+ end # class Sleep
33
+
34
+ end # module Strategies
35
+
36
+ end # module Uttk
@@ -0,0 +1,120 @@
1
+ # Author:: Vincent Cuissard <cuissa_v@epita.fr>
2
+ # Copyright:: Copyright (c) 2004, 2005 Uttk team. All rights reserved.
3
+ # License:: LGPL
4
+ # $Id: /fey/uttk/trunk/lib/uttk/strategies/SqlQuery.rb 8789 2005-09-27T14:49:49.088376Z ertai $
5
+
6
+
7
+ module Uttk
8
+
9
+ module Strategies
10
+
11
+ #
12
+ # This strategy manage _SQL_ base tests.
13
+ # It use unit testing (EXCEPT ALL query) for checking results.
14
+ # To use it, you need to have _dbi_ installed on your test system
15
+ # and have a database with these things:
16
+ # * a test schema (MY)
17
+ # * a reference schema (REF)
18
+ #
19
+ # After that you have just to write all queries that you want to test.
20
+ # Queries will be called on each schema by applying a delta operation:
21
+ # (REF ` MY) U (MY ` REF).
22
+ #
23
+ # In queries, %s will be replaced by given schemas.
24
+ #
25
+
26
+ class SqlQuery < Strategy
27
+ include Concrete
28
+
29
+ @@db = nil
30
+
31
+ #
32
+ # Methods
33
+ #
34
+
35
+ def prologue
36
+ super
37
+ if @@db.nil?
38
+ require 'dbi'
39
+ # Check if driver is available
40
+ if DBI.available_drivers.to_s !~ /#@driver/
41
+ raise_error("Unknown driver: #@driver")
42
+ else
43
+ # Start DB connection
44
+ @@db = DBI.connect("DBI:#@driver:host=#@host;database=#@database",
45
+ @user, @passwd)
46
+ end
47
+ end
48
+ end
49
+ protected :prologue
50
+
51
+
52
+ def run_impl
53
+ @delta = nil
54
+ begin
55
+ @delta = perform_delta
56
+ rescue DBI::DatabaseError => ex
57
+ fail(ex)
58
+ end
59
+ end
60
+ protected :run_impl
61
+
62
+
63
+ def assertion
64
+ unless @delta.nil?
65
+ @log.diff_output = @delta
66
+ fail('Delta not empty')
67
+ end
68
+ super
69
+ end
70
+ protected :assertion
71
+
72
+
73
+ def perform_delta
74
+ output_a = []
75
+ output_b = []
76
+
77
+ # Make queries
78
+ ref_query = @query.gsub(/%s/, @ref_schema)
79
+ my_query = @query.gsub(/%s/, @my_schema)
80
+
81
+ # Perform REF ` MY
82
+ @@db.execute("#{ref_query} EXCEPT ALL #{my_query}").fetch do |row|
83
+ output_a << row.join(' | ')
84
+ end
85
+
86
+ # Perform MY ` REF
87
+ @@db.execute("#{my_query} EXCEPT ALL #{ref_query}").fetch do |row|
88
+ output_b << row.join(' | ')
89
+ end
90
+
91
+ # REF DELTA MY => (REF ` MY) U (MY ` REF) = {}
92
+ # Check this
93
+ return nil if output_a.empty? and output_b.empty?
94
+
95
+ # Make report
96
+ { :'REF ` MY' => output_a.join("\n"),
97
+ :'MY ` REF' => output_b.join("\n") }
98
+ end
99
+ private :perform_delta
100
+
101
+ #
102
+ # Attributes
103
+ #
104
+
105
+ attribute :my_schema, 'Test schema', 'my'
106
+ attribute :ref_schema, 'Reference schema', 'ref'
107
+ attribute :query, 'SQL query (%s for the schema)', :mandatory
108
+ attribute :driver, 'SQL server driver', :mandatory
109
+ attribute :database, 'SQL database name', :mandatory
110
+ attribute :host, 'SQL server host', :mandatory
111
+ attribute :user, 'SQL user', :mandatory
112
+ attribute :passwd, 'SQL pass', :mandatory
113
+
114
+ end # class SqlQuery
115
+
116
+ end # module Strategies
117
+
118
+ end # module Uttk
119
+
120
+
@@ -0,0 +1,683 @@
1
+ # Author:: The Uttk Team.
2
+ # Copyright:: Copyright (c) 2004, 2005 Uttk team. All rights reserved.
3
+ # License:: LGPL
4
+ # $Id: /w/fey/uttk/trunk/lib/uttk/strategies/Strategy.rb 22184 2006-02-23T16:12:25.225774Z pouillar $
5
+
6
+
7
+ require 'set'
8
+ require 'timeout'
9
+
10
+ module Uttk
11
+
12
+ # A tutorial introduces how to create new strategies at
13
+ # http://uttk.org/shelf/documentation
14
+ module Strategies
15
+
16
+ # This is the base class for anything _testable_. It provides some basics
17
+ # attributes like the name of the test.
18
+ class Strategy
19
+ include Abstract
20
+ include AttributedClass
21
+
22
+ class AttributedClass::Attribute
23
+ alias :initialize_without_expand :initialize
24
+ def initialize ( name, desc, *a, &b )
25
+ my, our = a.partition { |x| x == :dont_expand }
26
+ @expand = my.empty?
27
+ initialize_without_expand(name, desc, *our, &b)
28
+ end
29
+
30
+ def expand?
31
+ @expand
32
+ end
33
+ end
34
+
35
+ #
36
+ # Accessors
37
+ #
38
+
39
+ attr_reader :status
40
+
41
+
42
+ #
43
+ # Constructor
44
+ #
45
+
46
+ # Create a new Strategy with the given optional document.
47
+ def initialize ( name=nil, &block )
48
+ @status = StartStatus.new
49
+ @symbols = {}
50
+ @symtbl = nil
51
+ initialize_attributes
52
+ @save = nil
53
+ @reject = Set.new
54
+ self.name = name
55
+ if block
56
+ if block.arity == -1
57
+ instance_eval(&block)
58
+ else
59
+ block[self]
60
+ end
61
+ end
62
+ end
63
+
64
+ module UttkTimeout
65
+ module_function
66
+ def timeout(sec, flow, exception=Error, &block)
67
+ return block[] if sec == nil or sec.zero?
68
+ begin
69
+ x = Thread.current
70
+ y = Thread.start do
71
+ sleep sec
72
+ if x.alive?
73
+ flow << :abort
74
+ x.raise exception, "execution expired"
75
+ end
76
+ end
77
+ block[sec]
78
+ ensure
79
+ y.kill if y and y.alive?
80
+ end
81
+ end
82
+ end # module UttkTimeout
83
+
84
+ #
85
+ # Methods
86
+ #
87
+
88
+ # Runs this test, proceding like this:
89
+ # - check_pre_assertion
90
+ # - prologue
91
+ # - run_impl
92
+ # - assertion
93
+ # - check_post_assertion
94
+ # - epilogue
95
+ def run ( log=@symtbl[:log] )
96
+ unless @status.is_a? StartStatus
97
+ raise_error("This test was already run (#{self} : #{self.class})")
98
+ end
99
+ @log = log
100
+ @benchmark = []
101
+ initialize_flow_factory if @symtbl[:flow_factory].nil?
102
+ flow = @symtbl[:flow]
103
+ flow << :prologue
104
+
105
+ @status = RunningStatus.new
106
+ @thread = Thread.current
107
+
108
+ aborted = nil
109
+ weight_copy = nil
110
+
111
+ @upper = @log.upper
112
+ begin
113
+ begin
114
+
115
+ # Pre assertion
116
+ pre_assertion_failed = nil
117
+ begin
118
+ unless r = check_pre_assertion()
119
+ pre_assertion_failed = "Pre assertion failed (#{r.inspect})"
120
+ end
121
+ rescue Exception => ex
122
+ pre_assertion_failed = "Pre assertion failed (#{ex})"
123
+ end
124
+ if pre_assertion_failed
125
+ @log.new_node(to_s)
126
+ @symtbl[:flow] << :error
127
+ skip(pre_assertion_failed)
128
+ end
129
+
130
+ begin
131
+ @benchmark << Benchmark.measure('prologue') do
132
+ prologue()
133
+ weight_copy = @weight
134
+ end
135
+ # @log.flow_id = flow.i
136
+
137
+ # Catch all other exceptions and wrapped them in an error.
138
+ rescue Exception => ex
139
+ raise_error(ex)
140
+ end
141
+
142
+ msg = "abort '%name' with timeout #{@timeout}s"
143
+ specific_abort = TimeoutAbortStatus.new(msg)
144
+
145
+ begin
146
+ flow << :begin_run_impl
147
+ skip_if_cached
148
+ skip_wrt_rpath_and_rpath_exclude
149
+ UttkTimeout.timeout(@timeout, flow, specific_abort) do
150
+ @benchmark << Benchmark.measure('run') do
151
+ run_impl()
152
+ end
153
+ end
154
+ ensure
155
+ flow << :end_run_impl
156
+ end
157
+
158
+ # Post assertion
159
+ post_assertion_failed = nil
160
+ begin
161
+ unless r = check_post_assertion()
162
+ post_assertion_failed = "Post assertion failed (#{r.inspect})"
163
+ end
164
+ rescue Exception => ex
165
+ post_assertion_failed = "Post assertion failed (#{ex})"
166
+ end
167
+ fail(post_assertion_failed) if post_assertion_failed
168
+
169
+
170
+ # Assertion
171
+ assertion()
172
+
173
+
174
+ raise_error('no status given')
175
+
176
+ # Forward StatusException
177
+ rescue Status => ex
178
+ # Put the exception in `aborted' if it dosen't concern me and abort.
179
+ if ex.is_a? TimeoutAbortStatus
180
+ aborted = ex if ex != specific_abort
181
+ ex.reason.gsub!('%name', @name.to_s)
182
+ end
183
+ raise ex
184
+
185
+ # Catch all others exceptions and wrapped them in an error.
186
+ rescue Exception => ex
187
+ raise_error(ex)
188
+ end
189
+
190
+ # Threat Status exceptions
191
+ rescue Status => ex
192
+ begin
193
+
194
+ flow << :epilogue
195
+ @status = ex
196
+ # Call the specific hook (pass_hook, failed_hook...).
197
+ send(ex.hook_name)
198
+ unless pre_assertion_failed
199
+ @benchmark << Benchmark.measure('epilogue') do
200
+ epilogue()
201
+ end
202
+ end
203
+ rescue SynFlow::Error => ex
204
+ display_unexpected_synflow_exc ex, :epilogue
205
+
206
+ rescue Exception => ex
207
+ display_unexpected_exc ex
208
+ end
209
+
210
+ rescue Exception => ex
211
+ display_unexpected_exc ex
212
+ end
213
+
214
+ begin
215
+ if @symtbl[:benchmark] and (not @reject.include?(:benchmark))
216
+ @log.new_node(:benchmark, :ordered => true) do
217
+ @benchmark.each { |b| @log << b }
218
+ end
219
+ end
220
+ @log << status unless @reject.include?(:status)
221
+ @status.weight *= weight_copy
222
+ @upper.up
223
+ if cache = @symtbl[:cache]
224
+ cache[@symtbl[:pathname]] =
225
+ {
226
+ :status => @status,
227
+ :symtbl => @symtbl.local
228
+ }
229
+ end
230
+ @reject.clear if defined? @reject
231
+ clean_instance_variables
232
+ flow << :finish
233
+ rescue SynFlow::Error => ex
234
+ display_unexpected_synflow_exc ex, :finish
235
+ rescue Exception => ex
236
+ display_unexpected_exc ex
237
+ end
238
+ raise aborted unless aborted.nil?
239
+ return @status
240
+
241
+ end
242
+
243
+ alias call run
244
+
245
+ #
246
+ # Custom accessors
247
+ #
248
+
249
+ def wclass=(other)
250
+ if other.is_a?(Class)
251
+ @wclass = other
252
+ else
253
+ @wclass = Uttk::Weights.const_get(other.to_s)
254
+ end
255
+ end
256
+
257
+ #
258
+ # Assign
259
+ #
260
+
261
+ # Assign an attribute safely from a key:String and a value.
262
+ def assign_one(key, val, silent=false)
263
+ return if [:strategy].include? key.to_sym
264
+ meth = key.to_s + '='
265
+ if !val.nil?
266
+ if respond_to?(meth) or respond_to?(:method_missing)
267
+ send(meth, val)
268
+ elsif not silent
269
+ @log.warn { "Attribute #{key} not found for #{self.class}" }
270
+ end
271
+ end
272
+ end
273
+ protected :assign_one
274
+
275
+ # This can be overrided to specify which attribute is assign at last.
276
+ def assign_at_last
277
+ nil
278
+ end
279
+ protected :assign_at_last
280
+
281
+ # Assign a +hsh+ keeping at last the attribute referenced by
282
+ # _assign_at_last_.
283
+ def assign(hsh)
284
+ last = assign_at_last
285
+ hsh.each_pair { |key, val| assign_one(key, val) if key.to_sym != last }
286
+ assign_one(last, hsh[last]) if hsh.has_key? last
287
+ end
288
+
289
+ #
290
+ # Reject
291
+ #
292
+
293
+ def reject ( *att )
294
+ @reject += att.map! { |a| a.to_sym }
295
+ end
296
+
297
+ def initialize_flow_factory
298
+ factory = SynFlowFactory.new
299
+ factory <<
300
+ {
301
+ :start_st => {
302
+ :prologue => :prologue_st,
303
+ :not_running? => :start_st,
304
+ :end_run_impl => :after_run_st,
305
+ # :abort => :start_st,
306
+ :error => :error_st
307
+ },
308
+
309
+ :prologue_st => {
310
+ :begin_run_impl => :run_impl_st,
311
+ :error => :error_st
312
+ },
313
+
314
+ :run_impl_st => {
315
+ :prologue => :prologue_st,
316
+ :end_run_impl => :after_run_st,
317
+ :abort => :abort_st,
318
+ :error => :error_st
319
+ },
320
+
321
+ :after_run_st => {
322
+ :epilogue => :epilogue_st,
323
+ :error => :error_st
324
+ },
325
+
326
+ :epilogue_st => {
327
+ :finish => :start_st,
328
+ :error => :error_st
329
+ },
330
+
331
+ :abort_st => {
332
+ :end_run_impl => :after_run_abort_st,
333
+ :abort => :abort_st,
334
+ :error => :error_st
335
+ },
336
+
337
+ :after_run_abort_st => {
338
+ :epilogue => :epilogue_abort_st,
339
+ :abort => :after_run_abort_st,
340
+ :error => :error_st
341
+ },
342
+
343
+ :epilogue_abort_st => {
344
+ :finish => :start_st,
345
+ :error => :error_st
346
+ },
347
+
348
+ :error_st => {
349
+ :prologue => :prologue_st,
350
+ :begin_run_impl => :run_impl_st,
351
+ :end_run_impl => :after_run_st,
352
+ :epilogue => :epilogue_st,
353
+ :finish => :start_st,
354
+ :no_running? => :error_st,
355
+ :error => :error_st,
356
+ :abort => :abort_st
357
+ },
358
+ }
359
+ factory.initial = :start_st
360
+ @symtbl[:flow_factory] = factory
361
+ @symtbl[:flow] = factory.new_flow
362
+ end
363
+
364
+ def skip_if_cached
365
+ if cache = @symtbl[:use_cache]
366
+ me = cache[@symtbl[:pathname].to_sym]
367
+ if me and @symtbl[:cache_proc][self, me[:status]]
368
+ @symtbl.local.merge!(me[:symtbl])
369
+ skip(@wclass.new(me[:status].weight))
370
+ end
371
+ end
372
+ end
373
+
374
+ def skip_wrt_rpath_and_rpath_exclude
375
+ re = @symtbl[:rpath]
376
+ re_ex = @symtbl[:rpath_exclude]
377
+ lpath = @log.path
378
+ if re and not lpath.lpath_prefix re
379
+ skip(@wclass.new(:PASS))
380
+ end
381
+ if re_ex and lpath.rpath_prefix re_ex
382
+ skip(@wclass.new(:PASS))
383
+ end
384
+ end
385
+
386
+ def clean_instance_variables
387
+ attrs = Set.new(self.class.attributes.map { |a| "@#{a.name}" })
388
+ vars = Set.new(instance_variables)
389
+ exceptions = Set.new(%w[ @status @thread @symtbl ])
390
+ (vars - attrs - exceptions).each do |var|
391
+ remove_instance_variable var
392
+ end
393
+ end
394
+
395
+ def check_assertion ( header, assertion )
396
+ if assertion.is_a?(Proc)
397
+ instance_eval(&assertion)
398
+ else
399
+ instance_eval(assertion.to_s)
400
+ end
401
+ end
402
+ protected :check_assertion
403
+
404
+ def check_pre_assertion
405
+ check_assertion('pre-assertion', @pre_assertion)
406
+ end
407
+ protected :check_pre_assertion
408
+
409
+
410
+ # Display test attributes. Attributes displayed and their order is
411
+ # specified by the class attribute _attributes_.
412
+ def prologue
413
+ if @symtbl[:loader].nil?
414
+ raise ArgumentError, 'no loader in the symtbl'
415
+ end
416
+ @save = {}
417
+ res = OHash.new
418
+
419
+ check_attributes
420
+ each_attribute do |attr, val|
421
+ next if val.nil?
422
+ name = attr.name
423
+ if attr.expand? and new_val = val.symtbl_gsub(@symtbl)
424
+ @save[name] = val
425
+ val = new_val
426
+ send("#{name}=", val)
427
+ end
428
+ if attr.visible? and not @reject.include? name
429
+ res[name] = val unless val == attr.default or name == :name
430
+ end
431
+ end
432
+ @symbols.each do |k, v|
433
+ @symtbl[k] = v
434
+ end
435
+ unless self.name.nil? or @reject.include? :name
436
+ if @symtbl[:pathname].nil?
437
+ @symtbl[:pathname] = ('/' + self.name).to_sym
438
+ else
439
+ @symtbl[:pathname] = :"#{@symtbl[:pathname]}/#{self.name}"
440
+ end
441
+ @log.new_node(self.name, :type => self.class)
442
+ end
443
+ @log << res
444
+ end
445
+ protected :prologue
446
+
447
+
448
+ # Compute really the test, only this method can be time checked.
449
+ def run_impl
450
+ end
451
+ protected :run_impl
452
+
453
+
454
+ # Exploit the results and assert when you want
455
+ def assertion
456
+ end
457
+ protected :assertion
458
+
459
+
460
+ def check_post_assertion
461
+ check_assertion('post-assertions', @post_assertion)
462
+ end
463
+ protected :check_post_assertion
464
+
465
+
466
+ # Display conclusions.
467
+ # Here you can finish some tasks even when the test fails.
468
+ # Exceptions are absolutly forbidden in this method.
469
+ def epilogue
470
+ unless @save.nil?
471
+ @save.each { |k,v| send("#{k}=", v) }
472
+ @save.clear
473
+ end
474
+ end
475
+ protected :epilogue
476
+
477
+ # Here you can do some tasks when the test failed.
478
+ def failed_hook
479
+ end
480
+ protected :failed_hook
481
+
482
+ # Here you can do some tasks when an error occur during the test.
483
+ def error_hook
484
+ end
485
+ protected :error_hook
486
+
487
+ # Here you can do some tasks when the test is aborted.
488
+ def abort_hook
489
+ end
490
+ protected :abort_hook
491
+
492
+ # Here you can do some task when the test is skiped.
493
+ def skip_hook
494
+ end
495
+ protected :skip_hook
496
+
497
+ # Here you can do some tasks when the test is passed.
498
+ def pass_hook
499
+ end
500
+ protected :pass_hook
501
+
502
+
503
+
504
+ #
505
+ # Assertions
506
+ #
507
+
508
+ def raise_status ( status )
509
+ @thread.raise(status)
510
+ end
511
+ protected :raise_status
512
+
513
+ def raise_status_custom ( status_class, *args )
514
+ weight, message = args.partition { |x| x.is_a? Weights::Weight }
515
+ if weight.size > 1 or message.size > 1
516
+ raise ArgumentError, 'too much arguments'
517
+ end
518
+ raise_status status_class.new(weight[0], message[0])
519
+ end
520
+ protected :raise_status_custom
521
+
522
+ # Force the test to pass
523
+ def pass
524
+ raise_status PassStatus.new
525
+ end
526
+
527
+ # Skip the test
528
+ def skip ( *args )
529
+ raise_status_custom SkipStatus, *args
530
+ end
531
+
532
+ # Force an Error status
533
+ def raise_error ( message=nil )
534
+ @symtbl[:flow] << :error
535
+ raise_status ErrorStatus.new(message)
536
+ end
537
+
538
+ # Force the test to fail
539
+ def fail ( *args )
540
+ raise_status_custom FailStatus, *args
541
+ end
542
+
543
+ # Abort the test explicitly.
544
+ def abort ( message='abort explicitly' )
545
+ @symtbl[:flow] << :abort
546
+ raise_status AbortStatus.new(message)
547
+ end
548
+
549
+
550
+ #
551
+ # Build methods
552
+ #
553
+
554
+ def testify ( symtbl, &block )
555
+ test = dup
556
+ test.symtbl ||= symtbl
557
+ block[test] if block
558
+ test
559
+ end
560
+
561
+ def to_s
562
+ @name || @log.path.to_s || super
563
+ end
564
+
565
+ def name= ( anObject )
566
+ case anObject
567
+ when nil, ''
568
+ @name = nil
569
+ else
570
+ @name = anObject.to_s
571
+ end
572
+ end
573
+
574
+
575
+ def timeout=(other)
576
+ if other >= 0
577
+ @timeout = other
578
+ else
579
+ raise(ArgumentError, "`#{other}' - timeout delay must be >= 0")
580
+ end
581
+ end
582
+
583
+ def running?
584
+ defined? @status and @status.is_a? RunningStatus
585
+ end
586
+
587
+ def display_unexpected_exc ( exc )
588
+ @log.error_unexpected_exception = exc
589
+ end
590
+
591
+ def display_unexpected_synflow_exc ( exc, arg )
592
+ @log.error_unexpected_synflow_exception = arg
593
+ end
594
+
595
+ # FIXME: I'm not well dumped
596
+ def symbols= ( symbols )
597
+ symbols.each do |k, v|
598
+ @symbols[k] = v
599
+ end
600
+ end
601
+
602
+ def strategy
603
+ self.class
604
+ end
605
+
606
+ def strategy= ( aClass )
607
+ if aClass != Strategy and aClass != self.class
608
+ raise ArgumentError, "Cannot change the strategy class " +
609
+ "of a test (#{aClass} != #{self.class})"
610
+ end
611
+ end
612
+
613
+ def symtbl= ( aSymtbl )
614
+ @symtbl = aSymtbl
615
+ @log ||= @symtbl[:log]
616
+ end
617
+
618
+ def symtbl (aSymtbl=nil)
619
+ if aSymtbl.nil?
620
+ @symtbl
621
+ else
622
+ self.symtbl = aSymtbl
623
+ end
624
+ end
625
+
626
+ def self.to_yaml_type
627
+ name.sub(/^Uttk::Strategies/, '!S')
628
+ end
629
+
630
+ def self.to_form ( b )
631
+ b.form_tag do
632
+ b.table :class => 'uttk_attributes' do
633
+ attributes.each do |attribute|
634
+ b.tr :class => 'uttk_attribute' do
635
+ b.td(:class => 'uttk_attribute_description') do
636
+ b.itext! "#{attribute.name} (#{attribute.descr}): "
637
+ end
638
+ b.td(:class => 'uttk_attribute_field') do
639
+ attribute.to_form(b)
640
+ end
641
+ end
642
+ end
643
+ end
644
+ end
645
+ end
646
+
647
+ attribute :name, 'test name', :invisible, String
648
+ attribute :strategy, 'the strategy class',
649
+ Class, Strategy, :mandatory, :invisible
650
+ attribute :wclass, 'a class to control weights', Class, Weights::Default
651
+ attribute :weight, 'a sort of coefficient. See wclass', 1
652
+ attribute :fatal, 'if the test fail all the suite fail', false
653
+ attribute :timeout, 'a duration (in seconds) before failure', 0
654
+ attribute :symbols, 'some user defined symbols', Hash do {} end
655
+
656
+ assertions_classes = [String, Proc, TrueClass, FalseClass]
657
+ attribute :pre_assertion, 'ruby code to assert environment condition ' +
658
+ 'which must return true/false',
659
+ :invisible, assertions_classes do true end
660
+ attribute :post_assertion, 'ruby code to assert environment condition ' +
661
+ 'which must return true/false',
662
+ :invisible, assertions_classes do true end
663
+
664
+ end # class Strategy
665
+
666
+ each_module_name do |name|
667
+ YAML.add_builtin_type("S::#{name}") do |type, val|
668
+ unless val.is_a? Hash
669
+ raise ArgumentError, "#{type}: needs a Hash not a #{val.class} (#{val.inspect})"
670
+ end
671
+ if val.has_key? :strategy and val[:strategy].to_s != to_s
672
+ raise ArgumentError, "type conflict #{type} != #{val[:strategy]}"
673
+ end
674
+ val[:strategy] = Strategies.const_get(type.sub(/^.*S::/, ''))
675
+ val
676
+ end
677
+ end
678
+
679
+ end # module Strategies
680
+
681
+ end # module Uttk
682
+
683
+