Mxx_ru 1.1.0

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 (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
+