Mxx_ru 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/COPYING +26 -0
  2. data/NEWS +52 -0
  3. data/README +21 -0
  4. data/Rakefile +32 -0
  5. data/examples/exe_and_lib/main.cpp +15 -0
  6. data/examples/exe_and_lib/prj.rb +11 -0
  7. data/examples/exe_and_lib/say.cpp +13 -0
  8. data/examples/exe_and_lib/say.hpp +11 -0
  9. data/examples/exe_and_lib/say.rb +7 -0
  10. data/examples/exe_dll_lib/inout.cpp +15 -0
  11. data/examples/exe_dll_lib/inout.hpp +26 -0
  12. data/examples/exe_dll_lib/inout.rb +18 -0
  13. data/examples/exe_dll_lib/main.cpp +23 -0
  14. data/examples/exe_dll_lib/prj.rb +11 -0
  15. data/examples/exe_dll_lib/say.cpp +13 -0
  16. data/examples/exe_dll_lib/say.hpp +12 -0
  17. data/examples/exe_dll_lib/say.rb +9 -0
  18. data/examples/exe_dll_lib_2/build.rb +7 -0
  19. data/examples/exe_dll_lib_2/inout/inout.cpp +15 -0
  20. data/examples/exe_dll_lib_2/inout/inout.hpp +26 -0
  21. data/examples/exe_dll_lib_2/inout/prj.rb +16 -0
  22. data/examples/exe_dll_lib_2/main/main.cpp +23 -0
  23. data/examples/exe_dll_lib_2/main/prj.rb +9 -0
  24. data/examples/exe_dll_lib_2/say/prj.rb +8 -0
  25. data/examples/exe_dll_lib_2/say/say.cpp +13 -0
  26. data/examples/exe_dll_lib_2/say/say.hpp +12 -0
  27. data/examples/simple_exe/main.cpp +26 -0
  28. data/examples/simple_exe/prj.rb +7 -0
  29. data/lib/mxx_ru/abstract_target.rb +283 -0
  30. data/lib/mxx_ru/binary_target.rb +89 -0
  31. data/lib/mxx_ru/binary_unittest.rb +130 -0
  32. data/lib/mxx_ru/cpp/analyzer.rb +230 -0
  33. data/lib/mxx_ru/cpp/composite.rb +106 -0
  34. data/lib/mxx_ru/cpp/detect_toolset.rb +122 -0
  35. data/lib/mxx_ru/cpp/mode.rb +85 -0
  36. data/lib/mxx_ru/cpp/obj_placement.rb +321 -0
  37. data/lib/mxx_ru/cpp/qt.rb +333 -0
  38. data/lib/mxx_ru/cpp/rucodegen.rb +114 -0
  39. data/lib/mxx_ru/cpp/source_file.rb +71 -0
  40. data/lib/mxx_ru/cpp/target.rb +1371 -0
  41. data/lib/mxx_ru/cpp/toolset.rb +1029 -0
  42. data/lib/mxx_ru/cpp/toolsets/bcc_win32_5.rb +52 -0
  43. data/lib/mxx_ru/cpp/toolsets/bcc_win32_family.rb +451 -0
  44. data/lib/mxx_ru/cpp/toolsets/c89_etk_nsk.rb +56 -0
  45. data/lib/mxx_ru/cpp/toolsets/c89_nsk.rb +56 -0
  46. data/lib/mxx_ru/cpp/toolsets/c89_nsk_family.rb +273 -0
  47. data/lib/mxx_ru/cpp/toolsets/gcc_cygwin.rb +54 -0
  48. data/lib/mxx_ru/cpp/toolsets/gcc_family.rb +382 -0
  49. data/lib/mxx_ru/cpp/toolsets/gcc_linux.rb +60 -0
  50. data/lib/mxx_ru/cpp/toolsets/gcc_mingw.rb +144 -0
  51. data/lib/mxx_ru/cpp/toolsets/gcc_sparc_solaris.rb +87 -0
  52. data/lib/mxx_ru/cpp/toolsets/vc7.rb +62 -0
  53. data/lib/mxx_ru/cpp/toolsets/vc8.rb +452 -0
  54. data/lib/mxx_ru/cpp/toolsets/vc_family.rb +428 -0
  55. data/lib/mxx_ru/cpp.rb +36 -0
  56. data/lib/mxx_ru/ex.rb +134 -0
  57. data/lib/mxx_ru/makestyle_generator.rb +138 -0
  58. data/lib/mxx_ru/textfile_unittest.rb +284 -0
  59. data/lib/mxx_ru/util.rb +258 -0
  60. data/tests/c/pcre/chartables.c +183 -0
  61. data/tests/c/pcre/config.h +99 -0
  62. data/tests/c/pcre/dftables.c +167 -0
  63. data/tests/c/pcre/get.c +349 -0
  64. data/tests/c/pcre/internal.h +677 -0
  65. data/tests/c/pcre/maketables.c +140 -0
  66. data/tests/c/pcre/pcre.c +8304 -0
  67. data/tests/c/pcre/pcre.h +193 -0
  68. data/tests/c/pcre/pcre.rb +14 -0
  69. data/tests/c/pcre/pcredemo.c +316 -0
  70. data/tests/c/pcre/pcregrep.c +642 -0
  71. data/tests/c/pcre/pcreposix.c +305 -0
  72. data/tests/c/pcre/pcreposix.h +88 -0
  73. data/tests/c/pcre/pcretest.c +1483 -0
  74. data/tests/c/pcre/perltest +211 -0
  75. data/tests/c/pcre/printint.c +360 -0
  76. data/tests/c/pcre/study.c +472 -0
  77. data/tests/cpp/mswin_res_dll/build.rb +14 -0
  78. data/tests/cpp/mswin_res_dll/dll.cpp +17 -0
  79. data/tests/cpp/mswin_res_dll/dll.rb +30 -0
  80. data/tests/cpp/mswin_res_dll/dll.rc +48 -0
  81. data/tests/cpp/mswin_res_dll/h/dll.hpp +8 -0
  82. data/tests/cpp/mswin_res_dll/h/res.h +3 -0
  83. data/tests/cpp/mswin_res_dll/main.cpp +13 -0
  84. data/tests/cpp/mswin_res_dll/main.rb +20 -0
  85. data/tests/cpp/mswin_res_dll/res/tree_fol.bmp +0 -0
  86. data/tests/cpp/mswin_res_dll/res/tree_state_1.bmp +0 -0
  87. data/tests/cpp/mswin_res_dll/res/tree_state_2.bmp +0 -0
  88. data/tests/cpp/mswin_res_exe/build.rb +23 -0
  89. data/tests/cpp/mswin_res_exe/h/res.h +3 -0
  90. data/tests/cpp/mswin_res_exe/main.cpp +17 -0
  91. data/tests/cpp/mswin_res_exe/main.rc +48 -0
  92. data/tests/cpp/mswin_res_exe/res/tree_fol.bmp +0 -0
  93. data/tests/cpp/mswin_res_exe/res/tree_state_1.bmp +0 -0
  94. data/tests/cpp/mswin_res_exe/res/tree_state_2.bmp +0 -0
  95. data/tests/cpp/rucodegen/host_config.cpp +20 -0
  96. data/tests/cpp/rucodegen/host_config.rb +14 -0
  97. data/tests/cpp/rucodegen/impl/conn_params.cpp +7 -0
  98. data/tests/cpp/rucodegen/impl/conn_params.rb +14 -0
  99. data/tests/cpp/rucodegen/impl/h/conn_params.hpp +10 -0
  100. data/tests/cpp/rucodegen/prj.rb +17 -0
  101. data/tests/cpp/textfile_unittest/build.rb +8 -0
  102. data/tests/cpp/textfile_unittest/etalons/out_0.txt +0 -0
  103. data/tests/cpp/textfile_unittest/etalons/out_1.txt +1 -0
  104. data/tests/cpp/textfile_unittest/etalons/out_128.txt +128 -0
  105. data/tests/cpp/textfile_unittest/main.cpp +89 -0
  106. data/tests/cpp/textfile_unittest/prj.rb +8 -0
  107. data/tests/cpp/textfile_unittest/prj.ut.rb +18 -0
  108. data/tests/cpp/toolset_name.rb +6 -0
  109. data/tests/cpp/vc_cleanup/cout.log +72 -0
  110. data/tests/cpp/vc_cleanup/dll_hi.cpp +5 -0
  111. data/tests/cpp/vc_cleanup/exe_hi.cpp +10 -0
  112. data/tests/cpp/vc_cleanup/lib_hi.cpp +5 -0
  113. data/tests/cpp/vc_cleanup/prj_dll_no_implib.rb +10 -0
  114. data/tests/cpp/vc_cleanup/prj_dll_no_implib_simple_target_root.rb +11 -0
  115. data/tests/cpp/vc_cleanup/prj_dll_with_implib.rb +11 -0
  116. data/tests/cpp/vc_cleanup/prj_dll_with_implib_simple_target_root.rb +14 -0
  117. data/tests/cpp/vc_cleanup/prj_exe_no_implib.rb +10 -0
  118. data/tests/cpp/vc_cleanup/prj_exe_no_implib_simple_target_root.rb +11 -0
  119. data/tests/cpp/vc_cleanup/prj_lib.rb +10 -0
  120. data/tests/cpp/vc_cleanup/prj_lib_with_simple_target_root.rb +11 -0
  121. data/tests/cpp/vc_cleanup/tc_vc_cleanup.rb +60 -0
  122. data/tests/mxx_ru/change_default_value/ignoring_by_build_root/build.rb +8 -0
  123. data/tests/mxx_ru/change_default_value/ignoring_by_build_root/child_1.rb +5 -0
  124. data/tests/mxx_ru/change_default_value/ignoring_by_child_1/build.rb +7 -0
  125. data/tests/mxx_ru/change_default_value/ignoring_by_child_1/child_1.rb +5 -0
  126. data/tests/mxx_ru/change_default_value/ignoring_by_child_1/child_2.rb +5 -0
  127. data/tests/mxx_ru/change_default_value/ok/build.rb +8 -0
  128. data/tests/mxx_ru/change_default_value/ok/child_1.rb +8 -0
  129. data/tests/mxx_ru/tc_makestyle_generator.rb +117 -0
  130. data/tests/mxx_ru/vc8/tc_actual_manifest.rb +230 -0
  131. data/tests/mxx_ru/vc8/tc_append_mt_commands.rb +104 -0
  132. data/tests/mxx_ru/vc8/tc_default_manifest.rb +17 -0
  133. data/tests/mxx_ru/vc8/tc_define_manifest.rb +173 -0
  134. data/tests/mxx_ru/vc8/tc_drop_default_manifest.rb +16 -0
  135. data/tests/mxx_ru/vc8/tc_invalid_params.rb +81 -0
  136. data/tests/mxx_ru/vc8/ts_vc8.rb +10 -0
  137. data/tests/qt/aclock/aclock.cpp +148 -0
  138. data/tests/qt/aclock/aclock.h +45 -0
  139. data/tests/qt/aclock/main.cpp +28 -0
  140. data/tests/qt/aclock/prj.rb +21 -0
  141. data/tests/qt/iconview/main.cpp +76 -0
  142. data/tests/qt/iconview/prj.rb +21 -0
  143. data/tests/qt/toplevel/main.cpp +9 -0
  144. data/tests/qt/toplevel/options.ui +587 -0
  145. data/tests/qt/toplevel/options.ui.h +98 -0
  146. data/tests/qt/toplevel/prj.rb +21 -0
  147. metadata +241 -0
@@ -0,0 +1,138 @@
1
+ #--
2
+ # Copyright (c) 1996-2004, Yauheni Akhotnikau
3
+ # Copyright (c) 2004-2006, JSC Intervale
4
+ # Copyright (c) 2006, The Mxx_ru Project
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification,
8
+ # are permitted provided that the following conditions are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote products derived
16
+ # from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
+ # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #++
28
+
29
+ require 'mxx_ru/abstract_target.rb'
30
+
31
+ module Mxx_ru
32
+
33
+ # A Generator, which allows to define simple make rules in a project.
34
+ #
35
+ # For example, if it's needed to get from ddl file two other files,
36
+ # cpp and hpp, using typegen program, it should be done like that:
37
+ # generator( Mxx_ru::Makestyle_generator.new(
38
+ # [ "myfile.cpp", "myfile.hpp" ],
39
+ # [ "myfile.ddl" ],
40
+ # [ "typegen --from myfile.ddl --cpp myfile.cpp --header myfile.hpp" ] ) )
41
+ #
42
+ # NOTE: For C++ projects current value of sources_root isn't taken into account.
43
+ class Makestyle_generator < Abstract_generator
44
+ # File names list, which should be built by given generator.
45
+ attr_reader :target_files
46
+
47
+ # File names list, result files depends from.
48
+ attr_reader :dependencies
49
+
50
+ # Command list, which should be ran in a sequence to get result files.
51
+ attr_reader :build_cmds
52
+
53
+ # Command list, which should be ran in a sequence to remove result files.
54
+ #
55
+ # If this list is empty, removal of result files would occur on clean operation.
56
+ attr_reader :clean_cmds
57
+
58
+ # Constructor.
59
+ #
60
+ # [_a_target_files_] Result files list.
61
+ # [_a_dependencies_] Dependencies list.
62
+ # [_a_build_cmds_] Command list, which should be ran in a sequence to get result files.
63
+ # [_a_clean_cmds_] Command list, which should be ran in a sequence to remove result files.
64
+ #
65
+ # NOTE: Single values may be defined as a strings instead of vectors. For example:
66
+ # Mxx_ru::Makestyle_generator.new( "myfile.cpp", "myfile.ddl",
67
+ # [ "typegen --from myfile.ddl --to myfile.cpp" ] )
68
+ # It's the same as:
69
+ # Mxx_ru::Makestyle_generator.new( [ "myfile.cpp" ], [ "myfile.ddl" ],
70
+ # "typegen --from myfile.ddl --to myfile.cpp" )
71
+ #
72
+ def initialize(
73
+ a_target_files,
74
+ a_dependencies,
75
+ a_build_cmds,
76
+ a_clean_cmds = Array.new )
77
+
78
+ @target_files = make_array( a_target_files )
79
+ @dependencies = make_array( a_dependencies )
80
+ @build_cmds = make_array( a_build_cmds )
81
+ @clean_cmds = make_array( a_clean_cmds )
82
+ end
83
+
84
+ # Perform the build of result files.
85
+ #
86
+ # NOTE: _target_ argument is ignored.
87
+ def build( target )
88
+ need_build = false
89
+
90
+ # Checking all result files. If one of them is obsolete, performing rebuild.
91
+ index = 0
92
+ while !need_build && index != @target_files.size
93
+ if Target_state::EXISTS != Target_state.detect(
94
+ @target_files[ index ], @dependencies ).state
95
+ need_build = true
96
+ else
97
+ index += 1
98
+ end
99
+ end
100
+
101
+ if need_build
102
+ # It's required to run all commands to build target.
103
+ Abstract_target.run( @build_cmds, [] )
104
+ end
105
+ end
106
+
107
+ # Perform the cleanup of result files.
108
+ #
109
+ # NOTE: _target_ argument is ignored.
110
+ def clean( target )
111
+ # If cleanup commands weren't set, deleting result files.
112
+ # Otherwise, it's required to run all commands in a sequence,
113
+ # ignoring return codes.
114
+ if 0 != @clean_cmds.size
115
+ @clean_cmds.each do |c|
116
+ system( c )
117
+ end
118
+ else
119
+ @target_files.each do |f|
120
+ Util.delete_file( f )
121
+ end
122
+ end
123
+ end
124
+
125
+ protected
126
+ # Conversion of single object into a vector, which contains that object.
127
+ # If source object is a vector, it's returned without any operations on it.
128
+ def make_array( a_object )
129
+ if a_object.instance_of? Array
130
+ return a_object
131
+ end
132
+
133
+ return [ a_object ]
134
+ end
135
+ end
136
+
137
+ end
138
+
@@ -0,0 +1,284 @@
1
+ #--
2
+ # Copyright (c) 1996-2004, Yauheni Akhotnikau
3
+ # Copyright (c) 2004-2006, JSC Intervale
4
+ # Copyright (c) 2006, The Mxx_ru Project
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification,
8
+ # are permitted provided that the following conditions are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote products derived
16
+ # from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
+ # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #++
28
+
29
+ require 'mxx_ru/ex'
30
+ require 'mxx_ru/abstract_target'
31
+
32
+ module Mxx_ru
33
+
34
+ # The class of a target, which is binary unit-test application, which create
35
+ # one or many text files.
36
+ # Given target performs a build of application, and then runs it and compares results
37
+ # with files which contains correct results.
38
+ #
39
+ # The basic idea consists in the presence of project file, which controls the build
40
+ # of unit-test application. In that project file, target object is created, inherited
41
+ # from Mxx_ru::Binary_target.
42
+ # To start unit-test it's necessary to create one more file, where target object of
43
+ # Mxx_ru::Textfile_unittest_target class is created.
44
+ # For example:
45
+ #
46
+ # Unit-test application build file:
47
+ # Mxx_ru::setup_target(
48
+ # Mxx_ru::Cpp::Exe_target.new( "test/pack/prj.rb" ) {
49
+ # ...
50
+ # }
51
+ # )
52
+ #
53
+ # File to run unit-test:
54
+ # Mxx_ru::setup_target(
55
+ # Mxx_ru::Textfile_unittest_target.new(
56
+ # "test/pack/pack.ut.rb",
57
+ # "test/pack/prj.rb" ) {
58
+ #
59
+ # launch( "--loops 16 --out test/pack/out/16.txt",
60
+ # [ pair( "test/pack/out/16.txt",
61
+ # "test/pack/out/etalon/16.txt" ) ] )
62
+ #
63
+ # launch( "--loops 32 --out test/pack/out/32.txt",
64
+ # [ pair( "test/pack/out/32.txt",
65
+ # "test/pack/out/etalon/32.txt" ) ] )
66
+ # }
67
+ # )
68
+ #
69
+ # File which is using that unit-test.
70
+ # Mxx_ru::setup_target(
71
+ # Mxx_ru::Cpp::Composite_target( Mxx_ru::BUILD_ROOT ) {
72
+ # required_prj( "some/project/prj.rb" )
73
+ # required_prj( "test/pack/prj.ut.rb" )
74
+ # }
75
+ # )
76
+ #
77
+ class Textfile_unittest_target < Abstract_target
78
+
79
+ # Exception, thrown if one subordinated project generated more
80
+ # than one result name.
81
+ class Must_be_one_target_name_ex < Ex
82
+ # [_a_names_] Names generated.
83
+ def initialize( a_names )
84
+ super( "Only one name expected in [#{a_names.join(';')}]" )
85
+ end
86
+ end
87
+
88
+ # Exception, thrown if files are not equal.
89
+ class File_mismatch_ex < Build_ex
90
+ # [_a_cmdline_] Command string of test application.
91
+ # [_a_produced_] Name of file generated.
92
+ # [_a_etalon_] Name of file containing correct results.
93
+ # [_a_line_num_] String number where first mismatch was detected.
94
+ # [_a_produced_line_] String of generated file. Nil if EOF is reached.
95
+ # [_a_etalon_line_] String of correct file. Nil if EOF is reached.
96
+ def initialize( a_cmdline,
97
+ a_produced, a_etalon,
98
+ a_line_num,
99
+ a_produced_line, a_etalon_line )
100
+ a_produced_line = "<EOF>" if !a_produced_line
101
+ a_etalon_line = "<EOF>" if !a_etalon_line
102
+
103
+ super( a_cmdline, "Mismatch found in line #{a_line_num}. " +
104
+ "Line in '#{a_produced}' is '#{a_produced_line}'. " +
105
+ "Line in '#{a_etalon}' is '#{a_etalon_line}'" )
106
+ end
107
+ end
108
+
109
+ # Description of single pair of values compared.
110
+ class Pair
111
+ # Name of file generated.
112
+ attr_reader :produced
113
+ # Name of correct file.
114
+ attr_reader :etalon
115
+
116
+ # Constructor.
117
+ def initialize( a_produced, a_etalon )
118
+ @produced = a_produced
119
+ @etalon = a_etalon
120
+ end
121
+ end
122
+
123
+ # A single run of test application description.
124
+ class Launch
125
+ # Command line parameters.
126
+ # Empty string if no parameters.
127
+ attr_reader :cmdline
128
+ # Files list to compare after application executed.
129
+ # Should be Array of Pair.
130
+ attr_reader :pairs
131
+
132
+ # Constructor.
133
+ def initialize( a_cmdline, a_pairs )
134
+ @cmdline = a_cmdline
135
+ @pairs = a_pairs
136
+ end
137
+ end
138
+
139
+ # Target, responsible for build of unit-test application.
140
+ attr_reader :mxx_target_project
141
+ # True if build method was already executed.
142
+ attr_reader :mxx_build_state
143
+ # Description of test application runs.
144
+ # Array of Launch.
145
+ attr_reader :mxx_launches
146
+
147
+ # Constructor.
148
+ #
149
+ # [_a_alias_] Self alias.
150
+ # [_a_target_project_] Project, responsible for build of unit-test application.
151
+ def initialize( a_alias, a_target_project, &block )
152
+ super( a_alias )
153
+
154
+ @mxx_build_state = nil
155
+
156
+ @mxx_target_project = required_prj( a_target_project )
157
+
158
+ @mxx_launches = Array.new
159
+
160
+ instance_eval( &block ) if block
161
+ end
162
+
163
+ # Create description of file pairs to compare.
164
+ #
165
+ # [_a_produced_] Name of generated file.
166
+ # [_a_etalon_] Name of correct file.
167
+ def pair( a_produced, a_etalon )
168
+ return Pair.new( a_produced, a_etalon )
169
+ end
170
+
171
+ # Add description of sequental run of test application.
172
+ #
173
+ # [_a_cmdline_] Command line parameters. May be empty string of nil
174
+ # if no parameters required.
175
+ # [_a_pairs_] A list of pairs of file names to compare. Should be Array of
176
+ # values returned by pair() method.
177
+ #
178
+ # Comparation will be performed in order they are defined in _a_pairs_.
179
+ # Comparation is interrupted on first mismatch.
180
+ def launch( a_cmdline, a_pairs )
181
+ a_cmdline = "" if !a_cmdline
182
+ @mxx_launches << Launch.new( a_cmdline, a_pairs )
183
+ end
184
+
185
+ # Build subordinated project and run it.
186
+ #
187
+ # If unit-test application returns exit code not equal to 0, exception is thrown.
188
+ def build
189
+ if !@mxx_build_state
190
+ @mxx_target_project.build
191
+
192
+ # Determining the name of application, which should be run.
193
+ full_names = @mxx_target_project.mxx_full_targets_names
194
+ if 1 != full_names.size
195
+ raise Must_be_one_target_name_ex.new( full_names )
196
+ end
197
+
198
+ # No execution of commands in dry-run mode.
199
+ if !Mxx_ru::Util::Mode.instance.is_dry_run
200
+ puts "running unit test: #{full_names[0]}..."
201
+ do_all_launches( full_names[ 0 ] )
202
+ end
203
+
204
+ @mxx_build_state = Target_state.new( Target_state::REBUILT )
205
+ end
206
+
207
+ return @mxx_build_state
208
+ end
209
+
210
+ # Cleanup the project.
211
+ #
212
+ # Executes clean method from subordinated project.
213
+ # Deletes all files, defined as result files of unit-test application.
214
+ def clean
215
+ @mxx_target_project.clean
216
+
217
+ @mxx_launches.each { |launch|
218
+ launch.pairs.each { |pair|
219
+ Util.delete_file( pair.produced )
220
+ }
221
+ }
222
+ end
223
+
224
+ protected
225
+ # Perform all defined runs of test application.
226
+ # This method should not be executed in dry-run mode.
227
+ def do_all_launches( a_file_to_exec )
228
+ # On mswin32 platform if file name is in unix format and
229
+ # redirection of input/output is set, some problems with
230
+ # execution would occur.
231
+ native_file_name = Util::native_pathname( a_file_to_exec )
232
+
233
+ @mxx_launches.each { |launch|
234
+ cmdline = native_file_name + " " + launch.cmdline
235
+ puts "\tlaunching '#{cmdline}'..."
236
+ if !system( cmdline )
237
+ puts "\n\nunit test '#{cmdline}' FAILED! #{$?}"
238
+ raise Build_ex.new( cmdline, $? )
239
+ end
240
+
241
+ # Execution of application was successful.
242
+ # Let's compare files.
243
+ launch.pairs.each { |pair|
244
+ puts "\t\tcomparing '#{pair.produced}' and '#{pair.etalon}'"
245
+ do_file_compare( cmdline, pair.produced, pair.etalon )
246
+ }
247
+ }
248
+ end
249
+
250
+ # Perform comparation of two files.
251
+ # If they are not identical, File_mismatch_ex exception is thrown.
252
+ # If some system exceptions would occur (absence of file for example),
253
+ # Build_ex ewxception will be thrown.
254
+ def do_file_compare( a_cmdline, a_produced, a_etalon )
255
+ begin
256
+ produced_file = File.new( a_produced, "r" )
257
+ etalon_file = File.new( a_etalon, "r" )
258
+
259
+ line_num = 1
260
+ while true
261
+ l1 = produced_file.gets
262
+ l2 = etalon_file.gets
263
+
264
+ if l1 != l2
265
+ raise File_mismatch_ex.new( a_cmdline,
266
+ a_produced, a_etalon, line_num,
267
+ l1, l2 )
268
+ else
269
+ line_num += 1
270
+ if !l1
271
+ break
272
+ end
273
+ end
274
+ end
275
+
276
+ rescue Exception => ex
277
+ raise Build_ex.new( a_cmdline,
278
+ "Error during comparing files " +
279
+ "'#{a_produced}', '#{a_etalon}': #{ex}" )
280
+ end
281
+ end
282
+ end
283
+
284
+ end # module Mxx_ru
@@ -0,0 +1,258 @@
1
+ #--
2
+ # Copyright (c) 1996-2004, Yauheni Akhotnikau
3
+ # Copyright (c) 2004-2006, JSC Intervale
4
+ # Copyright (c) 2006, The Mxx_ru Project
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification,
8
+ # are permitted provided that the following conditions are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote products derived
16
+ # from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
+ # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26
+ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ #++
28
+
29
+ require 'rbconfig'
30
+ require 'singleton'
31
+
32
+ module Mxx_ru
33
+
34
+ module Util
35
+ # Regular expression to divide file name and it's extension.
36
+ MATCH_FILE_EXT_REGEX = Regexp.new( "^(.+)\\.([^\\./]+)$" )
37
+
38
+ # Ruby command line parameters, handled by Mxx_ru.
39
+ MXXARG_CLEAN = "--mxx-clean"
40
+ MXXARG_SHOW_CMD = "--mxx-show-cmd"
41
+ MXXARG_KEEP_TMPS = "--mxx-keep-tmps"
42
+ MXXARG_SHOW_TMPS = "--mxx-show-tmps"
43
+ MXXARG_DRY_RUN = "--mxx-dry-run"
44
+
45
+ # OS name, script is run on.
46
+ @@host_os = nil
47
+
48
+ # Class, which detects Mxx_ru current mode.
49
+ class Mode
50
+ include Singleton
51
+
52
+ attr_reader :is_clean
53
+ attr_reader :is_show_cmd
54
+ attr_reader :is_keep_tmps
55
+ attr_reader :is_show_tmps
56
+
57
+ # Constructor checks for special arguments in command line.
58
+ def initialize
59
+ @is_clean = ARGV.include?( MXXARG_CLEAN )
60
+ @is_show_cmd = ARGV.include?( MXXARG_SHOW_CMD )
61
+ @is_keep_tmps = ARGV.include?( MXXARG_KEEP_TMPS )
62
+ @is_show_tmps = ARGV.include?( MXXARG_SHOW_TMPS )
63
+ @is_dry_run = ARGV.include?( MXXARG_DRY_RUN )
64
+ @is_manual_dry_run = false
65
+ end
66
+
67
+ # Is dry-run mode set?
68
+ # Dry-run mode is set, if --mxx-dry-run command line parameter is set,
69
+ # or if it's manually set.
70
+ def is_dry_run
71
+ return ( @is_dry_run || @is_manual_dry_run )
72
+ end
73
+
74
+ # On/Off manual dry-run mode.
75
+ # In some cases it's efficient to turn it on for some time.
76
+ # For example, it's used to handle subprojects with --mxx-cpp-1 option set.
77
+ def manual_dry_run( a_is_manual_dry_run )
78
+ @is_manual_dry_run = a_is_manual_dry_run
79
+ end
80
+
81
+ end
82
+
83
+ # Returns file name without last extension.
84
+ def Util.remove_file_ext( a_name )
85
+ match_result = MATCH_FILE_EXT_REGEX.match( a_name )
86
+ if nil == match_result
87
+ # No extension was present.
88
+ return String.new( a_name )
89
+ end
90
+
91
+ return match_result[ 1 ]
92
+ end
93
+
94
+ # Returns filename with new last extension.
95
+ def Util.change_file_ext( name, ext )
96
+ remove_file_ext( name ) + ext
97
+ end
98
+
99
+ # Deleting file name without exception.
100
+ def Util.delete_file( a_name )
101
+ if FileTest.exists?( a_name )
102
+ File.delete( a_name )
103
+ end
104
+ end
105
+
106
+ # Class, responsible for creation and removal of temporary files.
107
+ # Temporary files are created in current folder.
108
+ # Temporary files are removed before application is exitted,
109
+ # if --mxx-keep-tmps option isn't set.
110
+ class Tmp_files
111
+ include Singleton
112
+
113
+ # Temporary file names.
114
+ @@names = Array.new
115
+
116
+ def initialize
117
+ if !Mode.instance.is_keep_tmps
118
+ ObjectSpace.define_finalizer( self, Proc.new{ Tmp_files.finalizer } )
119
+ end
120
+
121
+ # Counter to ensure unique file names.
122
+ @current = 0
123
+
124
+ # Indicies stack in @@names for push and pop methods.
125
+ @index_stack = Array.new
126
+ end
127
+
128
+ def Tmp_files.finalizer
129
+ @@names.each { |d|
130
+ begin
131
+ File.delete( d )
132
+ rescue Exception => e
133
+ puts e
134
+ end
135
+ }
136
+ end
137
+
138
+ # Temporary file creation.
139
+ # The string given is stored to the temporary file.
140
+ # The name of temporary file is returned.
141
+ #
142
+ # [_a_content_] Should be an object of String type.
143
+ def create( a_content )
144
+
145
+ current = (@current += 1)
146
+ file_name = "tmpmxx_ru.#{$$}.#{current}"
147
+ file = File.new( file_name, "w" )
148
+ @@names << file_name
149
+ file << a_content
150
+ file.close
151
+
152
+ if Mode.instance.is_show_tmps
153
+ puts "<<<[#{file_name}]\t #{a_content}>>>"
154
+ end
155
+
156
+ return file_name
157
+ end
158
+
159
+ # Storing current vector size to the indicies stack.
160
+ def push()
161
+ if !Mode.instance.is_keep_tmps
162
+ @index_stack.push( @@names.size() )
163
+ end
164
+ end
165
+
166
+ # Removing all files, which are stored in a file names vector
167
+ # starting from first element from @index_stack position.
168
+ def pop()
169
+ if !Mode.instance.is_keep_tmps
170
+ index = @index_stack.pop
171
+ while @@names.size > index
172
+ file_to_delete = @@names.pop
173
+ Mxx_ru::Util::delete_file( file_to_delete )
174
+ end
175
+ end
176
+ end
177
+
178
+ end # class Tmp_files
179
+
180
+ # Auxiliary function for correct execution of build method of target object.
181
+ # Before execution Tmp_files.push is executed, and after execution of build method
182
+ # Tmp_files.pop is called. This way we are removing temporary files
183
+ # created during a compilation of given target.
184
+ def Util.build_call_wrapper( a_target )
185
+ begin
186
+ Tmp_files.instance.push
187
+ state = a_target.build
188
+ return state
189
+ ensure
190
+ Tmp_files.instance.pop
191
+ end
192
+ end
193
+
194
+ # Create folder if it isn't exist.
195
+ #
196
+ # All chain of names is tracked. For example, if we trying to create
197
+ # output/release/lib folder, and only output is exists, then release/lib folders
198
+ # are created.
199
+ def Util.create_dir( a_name )
200
+ # Dividing the chain.
201
+ chain = Array.new
202
+ chain.unshift( a_name )
203
+
204
+ to_split = a_name.clone
205
+ while to_split != "."
206
+ r = File.split( to_split )
207
+ chain.unshift( to_split = r[ 0 ] )
208
+ end
209
+
210
+ chain.each { |d|
211
+ if !FileTest.exists?( d )
212
+ Dir.mkdir( d )
213
+ end
214
+ }
215
+ end
216
+
217
+ # To ensure folder is exist.
218
+ #
219
+ # If dry-run mode wasn't set, checking for existance.
220
+ # If it isn't exists, trying to create it.
221
+ #
222
+ # In a dry-run mode Mxx_ru always assumes folder is exists, even if it isn't.
223
+ def Util.ensure_path_exists( a_path_name )
224
+ if !Mxx_ru::Util::Mode.instance.is_dry_run
225
+ if !FileTest.exists?( a_path_name )
226
+ Mxx_ru::Util.create_dir( a_path_name )
227
+ end
228
+ end
229
+ end
230
+
231
+ # Get OS name where script is exeuted.
232
+ def Util.host_os
233
+ if !@@host_os
234
+ @@host_os = Config::CONFIG[ "host_os" ]
235
+ end
236
+
237
+ return @@host_os
238
+ end
239
+
240
+ # Transform separators in file names to correct ones on the given platform.
241
+ #
242
+ # For example on mswin32 we change "/" to "\".
243
+ #
244
+ # [_a_pathname_] Path to the file in unix style.
245
+ #
246
+ # *IMPORTANT! In current version only mswin32 platform is tracked!*
247
+ def Util.native_pathname( a_pathname )
248
+ if "mswin32" == Util::host_os
249
+ return a_pathname.gsub( "/", "\\" )
250
+ end
251
+
252
+ return a_pathname
253
+ end
254
+
255
+ end # module Util
256
+
257
+ end # module Mxx_ru
258
+