Mxx_ru 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +26 -0
- data/NEWS +52 -0
- data/README +21 -0
- data/Rakefile +32 -0
- data/examples/exe_and_lib/main.cpp +15 -0
- data/examples/exe_and_lib/prj.rb +11 -0
- data/examples/exe_and_lib/say.cpp +13 -0
- data/examples/exe_and_lib/say.hpp +11 -0
- data/examples/exe_and_lib/say.rb +7 -0
- data/examples/exe_dll_lib/inout.cpp +15 -0
- data/examples/exe_dll_lib/inout.hpp +26 -0
- data/examples/exe_dll_lib/inout.rb +18 -0
- data/examples/exe_dll_lib/main.cpp +23 -0
- data/examples/exe_dll_lib/prj.rb +11 -0
- data/examples/exe_dll_lib/say.cpp +13 -0
- data/examples/exe_dll_lib/say.hpp +12 -0
- data/examples/exe_dll_lib/say.rb +9 -0
- data/examples/exe_dll_lib_2/build.rb +7 -0
- data/examples/exe_dll_lib_2/inout/inout.cpp +15 -0
- data/examples/exe_dll_lib_2/inout/inout.hpp +26 -0
- data/examples/exe_dll_lib_2/inout/prj.rb +16 -0
- data/examples/exe_dll_lib_2/main/main.cpp +23 -0
- data/examples/exe_dll_lib_2/main/prj.rb +9 -0
- data/examples/exe_dll_lib_2/say/prj.rb +8 -0
- data/examples/exe_dll_lib_2/say/say.cpp +13 -0
- data/examples/exe_dll_lib_2/say/say.hpp +12 -0
- data/examples/simple_exe/main.cpp +26 -0
- data/examples/simple_exe/prj.rb +7 -0
- data/lib/mxx_ru/abstract_target.rb +283 -0
- data/lib/mxx_ru/binary_target.rb +89 -0
- data/lib/mxx_ru/binary_unittest.rb +130 -0
- data/lib/mxx_ru/cpp/analyzer.rb +230 -0
- data/lib/mxx_ru/cpp/composite.rb +106 -0
- data/lib/mxx_ru/cpp/detect_toolset.rb +122 -0
- data/lib/mxx_ru/cpp/mode.rb +85 -0
- data/lib/mxx_ru/cpp/obj_placement.rb +321 -0
- data/lib/mxx_ru/cpp/qt.rb +333 -0
- data/lib/mxx_ru/cpp/rucodegen.rb +114 -0
- data/lib/mxx_ru/cpp/source_file.rb +71 -0
- data/lib/mxx_ru/cpp/target.rb +1371 -0
- data/lib/mxx_ru/cpp/toolset.rb +1029 -0
- data/lib/mxx_ru/cpp/toolsets/bcc_win32_5.rb +52 -0
- data/lib/mxx_ru/cpp/toolsets/bcc_win32_family.rb +451 -0
- data/lib/mxx_ru/cpp/toolsets/c89_etk_nsk.rb +56 -0
- data/lib/mxx_ru/cpp/toolsets/c89_nsk.rb +56 -0
- data/lib/mxx_ru/cpp/toolsets/c89_nsk_family.rb +273 -0
- data/lib/mxx_ru/cpp/toolsets/gcc_cygwin.rb +54 -0
- data/lib/mxx_ru/cpp/toolsets/gcc_family.rb +382 -0
- data/lib/mxx_ru/cpp/toolsets/gcc_linux.rb +60 -0
- data/lib/mxx_ru/cpp/toolsets/gcc_mingw.rb +144 -0
- data/lib/mxx_ru/cpp/toolsets/gcc_sparc_solaris.rb +87 -0
- data/lib/mxx_ru/cpp/toolsets/vc7.rb +62 -0
- data/lib/mxx_ru/cpp/toolsets/vc8.rb +452 -0
- data/lib/mxx_ru/cpp/toolsets/vc_family.rb +428 -0
- data/lib/mxx_ru/cpp.rb +36 -0
- data/lib/mxx_ru/ex.rb +134 -0
- data/lib/mxx_ru/makestyle_generator.rb +138 -0
- data/lib/mxx_ru/textfile_unittest.rb +284 -0
- data/lib/mxx_ru/util.rb +258 -0
- data/tests/c/pcre/chartables.c +183 -0
- data/tests/c/pcre/config.h +99 -0
- data/tests/c/pcre/dftables.c +167 -0
- data/tests/c/pcre/get.c +349 -0
- data/tests/c/pcre/internal.h +677 -0
- data/tests/c/pcre/maketables.c +140 -0
- data/tests/c/pcre/pcre.c +8304 -0
- data/tests/c/pcre/pcre.h +193 -0
- data/tests/c/pcre/pcre.rb +14 -0
- data/tests/c/pcre/pcredemo.c +316 -0
- data/tests/c/pcre/pcregrep.c +642 -0
- data/tests/c/pcre/pcreposix.c +305 -0
- data/tests/c/pcre/pcreposix.h +88 -0
- data/tests/c/pcre/pcretest.c +1483 -0
- data/tests/c/pcre/perltest +211 -0
- data/tests/c/pcre/printint.c +360 -0
- data/tests/c/pcre/study.c +472 -0
- data/tests/cpp/mswin_res_dll/build.rb +14 -0
- data/tests/cpp/mswin_res_dll/dll.cpp +17 -0
- data/tests/cpp/mswin_res_dll/dll.rb +30 -0
- data/tests/cpp/mswin_res_dll/dll.rc +48 -0
- data/tests/cpp/mswin_res_dll/h/dll.hpp +8 -0
- data/tests/cpp/mswin_res_dll/h/res.h +3 -0
- data/tests/cpp/mswin_res_dll/main.cpp +13 -0
- data/tests/cpp/mswin_res_dll/main.rb +20 -0
- data/tests/cpp/mswin_res_dll/res/tree_fol.bmp +0 -0
- data/tests/cpp/mswin_res_dll/res/tree_state_1.bmp +0 -0
- data/tests/cpp/mswin_res_dll/res/tree_state_2.bmp +0 -0
- data/tests/cpp/mswin_res_exe/build.rb +23 -0
- data/tests/cpp/mswin_res_exe/h/res.h +3 -0
- data/tests/cpp/mswin_res_exe/main.cpp +17 -0
- data/tests/cpp/mswin_res_exe/main.rc +48 -0
- data/tests/cpp/mswin_res_exe/res/tree_fol.bmp +0 -0
- data/tests/cpp/mswin_res_exe/res/tree_state_1.bmp +0 -0
- data/tests/cpp/mswin_res_exe/res/tree_state_2.bmp +0 -0
- data/tests/cpp/rucodegen/host_config.cpp +20 -0
- data/tests/cpp/rucodegen/host_config.rb +14 -0
- data/tests/cpp/rucodegen/impl/conn_params.cpp +7 -0
- data/tests/cpp/rucodegen/impl/conn_params.rb +14 -0
- data/tests/cpp/rucodegen/impl/h/conn_params.hpp +10 -0
- data/tests/cpp/rucodegen/prj.rb +17 -0
- data/tests/cpp/textfile_unittest/build.rb +8 -0
- data/tests/cpp/textfile_unittest/etalons/out_0.txt +0 -0
- data/tests/cpp/textfile_unittest/etalons/out_1.txt +1 -0
- data/tests/cpp/textfile_unittest/etalons/out_128.txt +128 -0
- data/tests/cpp/textfile_unittest/main.cpp +89 -0
- data/tests/cpp/textfile_unittest/prj.rb +8 -0
- data/tests/cpp/textfile_unittest/prj.ut.rb +18 -0
- data/tests/cpp/toolset_name.rb +6 -0
- data/tests/cpp/vc_cleanup/cout.log +72 -0
- data/tests/cpp/vc_cleanup/dll_hi.cpp +5 -0
- data/tests/cpp/vc_cleanup/exe_hi.cpp +10 -0
- data/tests/cpp/vc_cleanup/lib_hi.cpp +5 -0
- data/tests/cpp/vc_cleanup/prj_dll_no_implib.rb +10 -0
- data/tests/cpp/vc_cleanup/prj_dll_no_implib_simple_target_root.rb +11 -0
- data/tests/cpp/vc_cleanup/prj_dll_with_implib.rb +11 -0
- data/tests/cpp/vc_cleanup/prj_dll_with_implib_simple_target_root.rb +14 -0
- data/tests/cpp/vc_cleanup/prj_exe_no_implib.rb +10 -0
- data/tests/cpp/vc_cleanup/prj_exe_no_implib_simple_target_root.rb +11 -0
- data/tests/cpp/vc_cleanup/prj_lib.rb +10 -0
- data/tests/cpp/vc_cleanup/prj_lib_with_simple_target_root.rb +11 -0
- data/tests/cpp/vc_cleanup/tc_vc_cleanup.rb +60 -0
- data/tests/mxx_ru/change_default_value/ignoring_by_build_root/build.rb +8 -0
- data/tests/mxx_ru/change_default_value/ignoring_by_build_root/child_1.rb +5 -0
- data/tests/mxx_ru/change_default_value/ignoring_by_child_1/build.rb +7 -0
- data/tests/mxx_ru/change_default_value/ignoring_by_child_1/child_1.rb +5 -0
- data/tests/mxx_ru/change_default_value/ignoring_by_child_1/child_2.rb +5 -0
- data/tests/mxx_ru/change_default_value/ok/build.rb +8 -0
- data/tests/mxx_ru/change_default_value/ok/child_1.rb +8 -0
- data/tests/mxx_ru/tc_makestyle_generator.rb +117 -0
- data/tests/mxx_ru/vc8/tc_actual_manifest.rb +230 -0
- data/tests/mxx_ru/vc8/tc_append_mt_commands.rb +104 -0
- data/tests/mxx_ru/vc8/tc_default_manifest.rb +17 -0
- data/tests/mxx_ru/vc8/tc_define_manifest.rb +173 -0
- data/tests/mxx_ru/vc8/tc_drop_default_manifest.rb +16 -0
- data/tests/mxx_ru/vc8/tc_invalid_params.rb +81 -0
- data/tests/mxx_ru/vc8/ts_vc8.rb +10 -0
- data/tests/qt/aclock/aclock.cpp +148 -0
- data/tests/qt/aclock/aclock.h +45 -0
- data/tests/qt/aclock/main.cpp +28 -0
- data/tests/qt/aclock/prj.rb +21 -0
- data/tests/qt/iconview/main.cpp +76 -0
- data/tests/qt/iconview/prj.rb +21 -0
- data/tests/qt/toplevel/main.cpp +9 -0
- data/tests/qt/toplevel/options.ui +587 -0
- data/tests/qt/toplevel/options.ui.h +98 -0
- data/tests/qt/toplevel/prj.rb +21 -0
- 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
|
data/lib/mxx_ru/util.rb
ADDED
@@ -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
|
+
|