testability-driver 1.0.3 → 1.0.4
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.
- data/lib/tdriver-devtools/behaviour/xml/rdoc_behaviour_xml_generator.rb +2 -2
- data/lib/tdriver-devtools/tdriver-devtools.rb +1 -1
- data/lib/tdriver-devtools/tests/feature_tests/lib/custom_rdoc_generator.rb +3 -3
- data/lib/tdriver/base/behaviour/behaviours/object_behaviour_composition.rb +6 -1
- data/lib/tdriver/base/behaviour/behaviours/object_behaviour_description.rb +5 -3
- data/lib/tdriver/base/behaviour/behaviours/object_composition.rb +1 -1
- data/lib/tdriver/base/behaviour/factory.rb +225 -225
- data/lib/tdriver/base/errors.rb +1 -1
- data/lib/tdriver/base/state_object.rb +227 -179
- data/lib/tdriver/base/sut/controller.rb +2 -2
- data/lib/tdriver/base/sut/factory.rb +190 -182
- data/lib/tdriver/base/sut/generic/behaviours/application.rb +69 -25
- data/lib/tdriver/base/sut/generic/behaviours/controller.rb +1 -1
- data/lib/tdriver/base/sut/generic/behaviours/find.rb +4 -4
- data/lib/tdriver/base/sut/generic/behaviours/flash_behaviour.rb +3 -3
- data/lib/tdriver/base/sut/generic/behaviours/sut.rb +350 -165
- data/lib/tdriver/base/sut/generic/behaviours/switchbox_behaviour.rb +9 -9
- data/lib/tdriver/base/sut/generic/behaviours/verification.rb +191 -103
- data/lib/tdriver/base/sut/generic/commands/application.rb +1 -1
- data/lib/tdriver/base/sut/generic/commands/key_sequence.rb +1 -1
- data/lib/tdriver/base/sut/generic/commands/screen_capture.rb +1 -1
- data/lib/tdriver/base/sut/generic/plugin.rb +1 -1
- data/lib/tdriver/base/sut/sut.rb +5 -1
- data/lib/tdriver/base/test_object/abstract.rb +136 -151
- data/lib/tdriver/base/test_object/adapter.rb +293 -82
- data/lib/tdriver/base/test_object/behaviours/syncronization.rb +20 -17
- data/lib/tdriver/base/test_object/behaviours/test_object.rb +159 -532
- data/lib/tdriver/base/test_object/cache.rb +1 -1
- data/lib/tdriver/base/test_object/factory.rb +254 -605
- data/lib/tdriver/base/test_object/identificator.rb +1 -1
- data/lib/tdriver/base/test_object/loader.rb +1 -1
- data/lib/tdriver/base/test_object/verification.rb +17 -17
- data/lib/tdriver/loader.rb +20 -9
- data/lib/tdriver/report/report.rb +5 -0
- data/lib/tdriver/report/report_creator.rb +2 -2
- data/lib/tdriver/report/report_cucumber_listener.rb +4 -4
- data/lib/tdriver/report/report_cucumber_reporter.rb +4 -4
- data/lib/tdriver/report/report_execution_statistics.rb +22 -22
- data/lib/tdriver/report/report_grouping.rb +2 -2
- data/lib/tdriver/report/report_javascript.rb +11 -4
- data/lib/tdriver/report/report_test_case_run.rb +2 -2
- data/lib/tdriver/report/report_test_run.rb +5 -5
- data/lib/tdriver/report/report_test_unit.rb +74 -26
- data/lib/tdriver/report/report_writer.rb +70 -13
- data/lib/tdriver/tdriver.rb +17 -8
- data/lib/tdriver/util/common/array.rb +1 -1
- data/lib/tdriver/util/common/crc16.rb +1 -1
- data/lib/tdriver/util/common/environment.rb +1 -1
- data/lib/tdriver/util/common/file.rb +18 -9
- data/lib/tdriver/util/common/gem.rb +1 -1
- data/lib/tdriver/util/common/hash.rb +21 -0
- data/lib/tdriver/util/common/kernel.rb +1 -1
- data/lib/tdriver/util/common/loader.rb +5 -2
- data/lib/tdriver/util/common/numeric.rb +54 -3
- data/lib/tdriver/util/common/retryable.rb +30 -12
- data/lib/tdriver/util/common/stackable.rb +185 -0
- data/lib/tdriver/util/common/string.rb +21 -5
- data/lib/tdriver/util/{dbaccess/dbaccess.rb → database/access.rb} +4 -1
- data/lib/tdriver/util/{dbaccess/dbconnection.rb → database/connection.rb} +3 -0
- data/lib/tdriver/util/{dbaccess → database}/error.rb +0 -1
- data/lib/tdriver/util/{dbaccess → database}/loader.rb +5 -6
- data/lib/tdriver/util/{dynamic_attribute_filter.rb → filters/dynamic_attributes.rb} +1 -1
- data/lib/tdriver/util/hooking/hooking.rb +477 -0
- data/lib/tdriver/util/loader.rb +35 -29
- data/lib/tdriver/util/localisation/error.rb +0 -1
- data/lib/tdriver/util/localisation/loader.rb +1 -4
- data/lib/tdriver/util/localisation/localisation.rb +30 -27
- data/lib/tdriver/util/{common.rb → logger/loader.rb} +2 -4
- data/lib/tdriver/util/logger/logger.rb +574 -0
- data/lib/tdriver/util/operator_data/loader.rb +4 -3
- data/lib/tdriver/util/operator_data/operator_data.rb +5 -5
- data/lib/tdriver/util/parameter/parameter.rb +7 -1
- data/lib/tdriver/util/parameter/parameter_hash.rb +1 -1
- data/lib/tdriver/util/parameter/parameter_template.rb +1 -1
- data/lib/tdriver/util/parameter/parameter_user_api.rb +28 -20
- data/lib/tdriver/util/parameter/parameter_xml.rb +1 -1
- data/lib/tdriver/util/plugin/abstract.rb +1 -1
- data/lib/tdriver/util/plugin/service.rb +1 -1
- data/lib/tdriver/util/{localisation.rb → recorder/loader.rb} +4 -3
- data/lib/tdriver/util/recorder/recorder.rb +66 -0
- data/lib/tdriver/util/recorder/scripter.rb +258 -0
- data/lib/tdriver/util/{stats.rb → statistics/statistics.rb} +7 -8
- data/lib/tdriver/util/user_data/error.rb +0 -1
- data/lib/tdriver/util/user_data/loader.rb +1 -2
- data/lib/tdriver/util/user_data/user_data.rb +6 -6
- data/lib/tdriver/util/video/camera.rb +67 -0
- data/lib/tdriver/util/video/camera_linux.rb +139 -0
- data/lib/tdriver/util/video/camera_windows.rb +174 -0
- data/lib/tdriver/util/video/loader.rb +31 -0
- data/lib/tdriver/util/video/video_utils.rb +139 -0
- data/lib/tdriver/util/xml/abstraction.rb +56 -5
- data/lib/tdriver/util/xml/builder.rb +2 -5
- data/lib/tdriver/util/{parameter.rb → xml/comment.rb} +10 -2
- data/lib/tdriver/util/xml/loader.rb +32 -22
- data/lib/tdriver/util/xml/nil_node.rb +2 -2
- data/lib/tdriver/util/xml/parsers/loader.rb +0 -1
- data/lib/tdriver/util/xml/parsers/nokogiri/abstraction.rb +18 -44
- data/lib/tdriver/util/xml/parsers/nokogiri/attribute.rb +9 -13
- data/lib/tdriver/util/xml/parsers/nokogiri/builder.rb +9 -3
- data/lib/tdriver/util/xml/parsers/nokogiri/comment.rb +39 -0
- data/lib/tdriver/util/xml/parsers/nokogiri/document.rb +6 -11
- data/lib/tdriver/util/xml/parsers/nokogiri/element.rb +2 -122
- data/lib/tdriver/util/xml/parsers/nokogiri/loader.rb +26 -16
- data/lib/tdriver/util/xml/parsers/nokogiri/node.rb +203 -0
- data/lib/tdriver/util/xml/parsers/nokogiri/nodeset.rb +1 -2
- data/lib/tdriver/util/xml/parsers/nokogiri/text.rb +2 -20
- data/lib/tdriver/util/xml/xml.rb +52 -20
- data/lib/tdriver/verify/verify.rb +238 -81
- data/xml/behaviours/generic.xml +12 -10
- metadata +156 -180
- data/lib/tdriver/base/test_object/factory_new.rb +0 -202
- data/lib/tdriver/util/hooking.rb +0 -434
- data/lib/tdriver/util/logger.rb +0 -506
- data/lib/tdriver/util/recorder.rb +0 -297
- data/lib/tdriver/util/video_utils.rb +0 -384
- data/lib/tdriver/util/xml/nil_element.rb +0 -89
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
############################################################################
|
|
2
|
-
##
|
|
3
|
-
## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
|
4
|
-
## All rights reserved.
|
|
5
|
-
## Contact: Nokia Corporation (testabilitydriver@nokia.com)
|
|
6
|
-
##
|
|
7
|
-
## This file is part of Testability Driver.
|
|
8
|
-
##
|
|
9
|
-
## If you have questions regarding the use of this file, please contact
|
|
10
|
-
## Nokia at testabilitydriver@nokia.com .
|
|
11
|
-
##
|
|
12
|
-
## This library is free software; you can redistribute it and/or
|
|
13
|
-
## modify it under the terms of the GNU Lesser General Public
|
|
14
|
-
## License version 2.1 as published by the Free Software Foundation
|
|
15
|
-
## and appearing in the file LICENSE.LGPL included in the packaging
|
|
16
|
-
## of this file.
|
|
17
|
-
##
|
|
18
|
-
############################################################################
|
|
19
|
-
|
|
20
|
-
module TDriver
|
|
21
|
-
|
|
22
|
-
class TestObjectFactory
|
|
23
|
-
|
|
24
|
-
attr_accessor :timeout, :retry_interval, :test_object_adapter
|
|
25
|
-
|
|
26
|
-
def initialize( test_object_adapter )
|
|
27
|
-
|
|
28
|
-
#@timeout = 5
|
|
29
|
-
|
|
30
|
-
#@retry_interval = 1
|
|
31
|
-
|
|
32
|
-
@test_object_adapter = test_object_adapter
|
|
33
|
-
|
|
34
|
-
@timeout = MobyUtil::Parameter[ :synchronization_timeout, "20" ].to_f
|
|
35
|
-
|
|
36
|
-
@retry_interval = MobyUtil::Parameter[ :synchronization_retry_interval, "1" ].to_f
|
|
37
|
-
|
|
38
|
-
end # initialize
|
|
39
|
-
|
|
40
|
-
def get_objects( source_data, rules, &block )
|
|
41
|
-
|
|
42
|
-
# __multiple_objects
|
|
43
|
-
# __all_children
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
#TDriver::TestObjectIdentificator.new( creation_hash )
|
|
47
|
-
# {:type=>"application", :name=>"calculator"}
|
|
48
|
-
|
|
49
|
-
test_object_attributes = rules[ :attributes ]
|
|
50
|
-
|
|
51
|
-
dynamic_attributes = strip_dynamic_attributes!( test_object_attributes )
|
|
52
|
-
|
|
53
|
-
# add keys from rules to dynamic attribute filter list -- to avoid IRB bug
|
|
54
|
-
MobyUtil::DynamicAttributeFilter.instance.add_attributes( rules.keys )
|
|
55
|
-
|
|
56
|
-
#p dynamic_attributes
|
|
57
|
-
#p rules
|
|
58
|
-
|
|
59
|
-
refresh = false
|
|
60
|
-
|
|
61
|
-
MobyUtil::Retryable.until(
|
|
62
|
-
|
|
63
|
-
:timeout => @timeout,
|
|
64
|
-
:interval => @retry_interval,
|
|
65
|
-
:exception => [ MobyBase::TestObjectNotFoundError, MobyBase::MultipleTestObjectsIdentifiedError ]
|
|
66
|
-
|
|
67
|
-
){
|
|
68
|
-
|
|
69
|
-
# refresh source data if refresh flag is set to true
|
|
70
|
-
source_data = yield( source_data ) if refresh
|
|
71
|
-
|
|
72
|
-
# set refresh flag to true
|
|
73
|
-
refresh = true
|
|
74
|
-
|
|
75
|
-
matches, rule = @test_object_adapter.get_objects( source_data, test_object_attributes )
|
|
76
|
-
|
|
77
|
-
# create string representation of hash merged with and dynamic attributes
|
|
78
|
-
rules_string = test_object_attributes.merge( dynamic_attributes ).inspect
|
|
79
|
-
|
|
80
|
-
# raise exception if multiple matches found
|
|
81
|
-
Kernel::raise MobyBase::MultipleTestObjectsIdentifiedError.new(
|
|
82
|
-
|
|
83
|
-
"Multiple test objects found with rule: #{ rules_string }"
|
|
84
|
-
|
|
85
|
-
) if !dynamic_attributes.has_key?( :__index ) and (!( rules[ :multiple_objects ] || false ) and matches.size > 1)
|
|
86
|
-
|
|
87
|
-
# raise exception if no matches found
|
|
88
|
-
Kernel::raise MobyBase::TestObjectNotFoundError.new(
|
|
89
|
-
|
|
90
|
-
"Cannot find object with rule: #{ rules_string }"
|
|
91
|
-
|
|
92
|
-
) if matches.size.zero?
|
|
93
|
-
|
|
94
|
-
# ... or proceed if no exceptions raised
|
|
95
|
-
|
|
96
|
-
# sort elements if required by caller
|
|
97
|
-
# @test_object_adapter.sort_elements....
|
|
98
|
-
|
|
99
|
-
# return only one element if index given
|
|
100
|
-
matches = [ matches[ dynamic_attributes[ :__index ] ] ] if dynamic_attributes.has_key?( :__index )
|
|
101
|
-
|
|
102
|
-
# return array of matching test object(s)
|
|
103
|
-
make_test_objects( matches, rules )
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
end # get_objects
|
|
108
|
-
|
|
109
|
-
private
|
|
110
|
-
|
|
111
|
-
def make_test_objects( matches, rules )
|
|
112
|
-
|
|
113
|
-
#p rules
|
|
114
|
-
|
|
115
|
-
sut = rules[ :sut ]
|
|
116
|
-
|
|
117
|
-
# return array of matching test object(s)
|
|
118
|
-
matches.collect{ | source_data |
|
|
119
|
-
|
|
120
|
-
# get test object type from xml
|
|
121
|
-
object_type = @test_object_adapter.test_object_attribute( 'type', source_data )
|
|
122
|
-
|
|
123
|
-
# create new test object instance
|
|
124
|
-
test_object = MobyBase::TestObject.new(
|
|
125
|
-
|
|
126
|
-
# test object factory
|
|
127
|
-
self,
|
|
128
|
-
|
|
129
|
-
# associated sut
|
|
130
|
-
sut,
|
|
131
|
-
|
|
132
|
-
# associated parent object; either test object, application or sut
|
|
133
|
-
rules[ :parent_object ],
|
|
134
|
-
|
|
135
|
-
# test object xml data
|
|
136
|
-
source_data
|
|
137
|
-
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
# apply object composition behaviour to test object
|
|
141
|
-
test_object.extend( MobyBehaviour::ObjectBehaviourComposition )
|
|
142
|
-
|
|
143
|
-
# TODO: behaviours should be applied by using BehaviourFactory directly
|
|
144
|
-
# apply behaviours to test object
|
|
145
|
-
test_object.apply_behaviour!(
|
|
146
|
-
:object_type => [ '*', object_type ],
|
|
147
|
-
:sut_type => [ '*', sut.ui_type ],
|
|
148
|
-
:input_type => [ '*', sut.input.to_s ],
|
|
149
|
-
:version => [ '*', sut.ui_version ]
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
# create child accessors
|
|
153
|
-
@test_object_adapter.create_child_accessors!( test_object, source_data )
|
|
154
|
-
|
|
155
|
-
# TODO: call verification block if defined (verify_ui_dump)
|
|
156
|
-
|
|
157
|
-
# # do not make test object verifications if we are operating on the
|
|
158
|
-
# # base sut itself (allow run to pass)
|
|
159
|
-
# unless parent.kind_of?( MobyBase::SUT )
|
|
160
|
-
# verify_ui_dump( sut ) unless sut.verify_blocks.empty?
|
|
161
|
-
# end
|
|
162
|
-
|
|
163
|
-
# pass test object with behaviours as result
|
|
164
|
-
test_object
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
end # make_test_objects
|
|
169
|
-
|
|
170
|
-
def strip_dynamic_attributes!( hash )
|
|
171
|
-
|
|
172
|
-
# remove dynamic attributes from hash and return as result
|
|
173
|
-
Hash[
|
|
174
|
-
|
|
175
|
-
# iterate through each hash key
|
|
176
|
-
hash.select{ | key, value |
|
|
177
|
-
|
|
178
|
-
# dynamic attribute name has "__" prefix
|
|
179
|
-
if key.to_s =~ /^__/
|
|
180
|
-
|
|
181
|
-
# remove dynamic attribute key from hash
|
|
182
|
-
hash.delete( key )
|
|
183
|
-
|
|
184
|
-
# add to hash
|
|
185
|
-
true
|
|
186
|
-
|
|
187
|
-
else
|
|
188
|
-
|
|
189
|
-
# do not add to hash
|
|
190
|
-
false
|
|
191
|
-
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
]
|
|
197
|
-
|
|
198
|
-
end # strip_dynamic_attributes!
|
|
199
|
-
|
|
200
|
-
end # TestObjectFactory
|
|
201
|
-
|
|
202
|
-
end # TDriver
|
data/lib/tdriver/util/hooking.rb
DELETED
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
############################################################################
|
|
2
|
-
##
|
|
3
|
-
## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
|
4
|
-
## All rights reserved.
|
|
5
|
-
## Contact: Nokia Corporation (testabilitydriver@nokia.com)
|
|
6
|
-
##
|
|
7
|
-
## This file is part of Testability Driver.
|
|
8
|
-
##
|
|
9
|
-
## If you have questions regarding the use of this file, please contact
|
|
10
|
-
## Nokia at testabilitydriver@nokia.com .
|
|
11
|
-
##
|
|
12
|
-
## This library is free software; you can redistribute it and/or
|
|
13
|
-
## modify it under the terms of the GNU Lesser General Public
|
|
14
|
-
## License version 2.1 as published by the Free Software Foundation
|
|
15
|
-
## and appearing in the file LICENSE.LGPL included in the packaging
|
|
16
|
-
## of this file.
|
|
17
|
-
##
|
|
18
|
-
############################################################################
|
|
19
|
-
module MobyUtil
|
|
20
|
-
|
|
21
|
-
class Hooking
|
|
22
|
-
|
|
23
|
-
include Singleton
|
|
24
|
-
|
|
25
|
-
attr_accessor :wrappee_count
|
|
26
|
-
attr_accessor :wrapped_methods
|
|
27
|
-
attr_accessor :benchmark
|
|
28
|
-
|
|
29
|
-
# list of non-wrappable methods
|
|
30
|
-
@@non_wrappable_methods = [ 'instance' ]
|
|
31
|
-
|
|
32
|
-
def initialize
|
|
33
|
-
|
|
34
|
-
# default values
|
|
35
|
-
@wrapped_methods = {}
|
|
36
|
-
|
|
37
|
-
@wrappee_count = 0
|
|
38
|
-
@benchmark = {}
|
|
39
|
-
|
|
40
|
-
@logger_method = nil
|
|
41
|
-
@logger_instance = nil
|
|
42
|
-
|
|
43
|
-
$mobyutil_hooking_instance = self
|
|
44
|
-
$mobyutil_hooking_elapsed_time = []
|
|
45
|
-
|
|
46
|
-
$mobyutil_hooking_start_benchmark_time = Time.now
|
|
47
|
-
$mobyutil_hooking_last_call_end_time = Time.now
|
|
48
|
-
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Function to set logger instance used by wrapper
|
|
52
|
-
# == params
|
|
53
|
-
# logger_instance:: Instance of TDriver logger
|
|
54
|
-
# == returns
|
|
55
|
-
def set_logger_instance( logger_instance )
|
|
56
|
-
|
|
57
|
-
@logger_instance = logger_instance
|
|
58
|
-
|
|
59
|
-
nil
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Function to create logger event - this method is called from wrapper
|
|
64
|
-
# == params
|
|
65
|
-
# text:: Text sent from wrapper
|
|
66
|
-
# arguments:: Not in use
|
|
67
|
-
# == returns
|
|
68
|
-
def log( text, *arguments )
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
unless @logger_instance.nil?
|
|
72
|
-
|
|
73
|
-
@logger_instance.debug( "%s" % text ) # if @logger_instance.enabled
|
|
74
|
-
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
#@logger_instance.log( "debug", "%s" % text ) unless @logger_instance.nil?
|
|
78
|
-
|
|
79
|
-
nil
|
|
80
|
-
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Function to hook all instance and static methods of target Class/Module
|
|
84
|
-
# == params
|
|
85
|
-
# base:: Target Class or Module
|
|
86
|
-
# == returns
|
|
87
|
-
def hook_methods( _base )
|
|
88
|
-
|
|
89
|
-
hook_static_methods( _base )
|
|
90
|
-
hook_instance_methods( _base )
|
|
91
|
-
|
|
92
|
-
nil
|
|
93
|
-
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def add_wrapper( wrapper )
|
|
97
|
-
|
|
98
|
-
@wrapped_methods.merge!( wrapper )
|
|
99
|
-
@wrappee_count += 1
|
|
100
|
-
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Function to update method runtime & calls count for benchmark
|
|
104
|
-
# == params
|
|
105
|
-
# method_name:: Name of the target method
|
|
106
|
-
# time_elapsed_in_subcalls::
|
|
107
|
-
# total_time_elapsed::
|
|
108
|
-
def update_method_benchmark( method_name, time_elapsed_in_subcalls, total_time_elapsed )
|
|
109
|
-
|
|
110
|
-
@benchmark[ method_name ].tap{ | hash |
|
|
111
|
-
|
|
112
|
-
hash[ :time_elapsed ] += ( total_time_elapsed - time_elapsed_in_subcalls )
|
|
113
|
-
hash[ :time_elapsed_total ] += total_time_elapsed
|
|
114
|
-
hash[ :times_called ] += 1
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def print_benchmark( rules = {} )
|
|
121
|
-
|
|
122
|
-
#total_run_time = $mobyutil_hooking_last_call_end_time - $mobyutil_hooking_start_benchmark_time
|
|
123
|
-
|
|
124
|
-
total_run_time = 0
|
|
125
|
-
|
|
126
|
-
# :sort => :total_time || :times_called || :average_time
|
|
127
|
-
|
|
128
|
-
rules = { :sort => :total_time, :order => :ascending, :show_uncalled_methods => true }.merge( rules )
|
|
129
|
-
|
|
130
|
-
puts "%-80s %8s %15s %15s %9s %15s" % [ 'Name:', 'Calls:', 'Time total:', 'W/O subcalls:', '%/run', 'Total/call:' ]
|
|
131
|
-
puts "%-80s %8s %15s %15s %9s %15s" % [ '-' * 80, '-' * 8, '-' * 15, '-' * 15, '-' * 8, '-' * 15 ]
|
|
132
|
-
|
|
133
|
-
# calculate average time for method
|
|
134
|
-
( table = @benchmark ).each{ | key, value |
|
|
135
|
-
|
|
136
|
-
table[ key ][ :average_time ] = ( value[ :times_elapsed_total ] == 0 || value[ :times_called ] == 0 ) ? 0 : value[ :time_elapsed_total ] / value[ :times_called ]
|
|
137
|
-
|
|
138
|
-
total_run_time += value[ :time_elapsed ]
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
table = table.sort{ | method_a, method_b |
|
|
143
|
-
|
|
144
|
-
case rules[ :sort ]
|
|
145
|
-
|
|
146
|
-
when :name
|
|
147
|
-
method_a[ 0 ] <=> method_b[ 0 ]
|
|
148
|
-
|
|
149
|
-
when :times_called
|
|
150
|
-
method_a[ 1 ][ :times_called ] <=> method_b[ 1 ][ :times_called ]
|
|
151
|
-
|
|
152
|
-
when :total_time
|
|
153
|
-
method_a[ 1 ][ :time_elapsed_total ] <=> method_b[ 1 ][ :time_elapsed_total ]
|
|
154
|
-
|
|
155
|
-
when :total_time_no_subs
|
|
156
|
-
method_a[ 1 ][ :time_elapsed ] <=> method_b[ 1 ][ :time_elapsed ]
|
|
157
|
-
|
|
158
|
-
when :percentage
|
|
159
|
-
|
|
160
|
-
( ( method_a[ 1 ][ :time_elapsed ].to_f / total_run_time.to_f ) * 100 ) <=> ( ( method_b[ 1 ][ :time_elapsed ].to_f / total_run_time.to_f ) * 100 )
|
|
161
|
-
|
|
162
|
-
when :average_time
|
|
163
|
-
method_a[ 1 ][ :average_time ] <=> method_b[ 1 ][ :average_time ]
|
|
164
|
-
|
|
165
|
-
else
|
|
166
|
-
|
|
167
|
-
Kernel::raise ArgumentError.new("Invalid sorting rule, valid rules are :name, :times_called, :total_time, :total_time_no_subs, :percentage or :average_time")
|
|
168
|
-
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
case rules[ :order ]
|
|
174
|
-
|
|
175
|
-
when :ascending
|
|
176
|
-
# do nothing
|
|
177
|
-
|
|
178
|
-
when :descending
|
|
179
|
-
table = table.reverse
|
|
180
|
-
|
|
181
|
-
else
|
|
182
|
-
|
|
183
|
-
Kernel::raise ArgumentError.new("Invalid sort order rule, valid rules are :ascending, :descending")
|
|
184
|
-
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
total_percentage = 0.0
|
|
188
|
-
total_time_elapsed_total = 0.0
|
|
189
|
-
total_average = 0.0
|
|
190
|
-
total_calls = 0
|
|
191
|
-
|
|
192
|
-
table.each{ | method |
|
|
193
|
-
|
|
194
|
-
puts "%-80s %8s %15.8f %15.8f %8.3f%% %15.8f" % [
|
|
195
|
-
method[ 0 ],
|
|
196
|
-
method[ 1 ][ :times_called ],
|
|
197
|
-
method[ 1 ][ :time_elapsed_total ],
|
|
198
|
-
method[ 1 ][ :time_elapsed ],
|
|
199
|
-
|
|
200
|
-
( ( method[ 1 ][ :time_elapsed ].to_f / total_run_time.to_f ) * 100 ),
|
|
201
|
-
|
|
202
|
-
method[ 1 ][ :average_time ]
|
|
203
|
-
] unless !rules[ :show_uncalled_methods ] && method[ 1 ][ :times_called ] == 0
|
|
204
|
-
|
|
205
|
-
total_percentage += ( ( method[ 1 ][ :time_elapsed ].to_f / total_run_time.to_f ) * 100 )
|
|
206
|
-
|
|
207
|
-
total_calls += method[ 1 ][ :times_called ]
|
|
208
|
-
total_time_elapsed_total += method[ 1 ][ :time_elapsed_total ]
|
|
209
|
-
total_average += method[ 1 ][ :average_time ]
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
puts "%-80s %8s %15s %15s %9s %15s" % [ '-' * 80, '-' * 8, '-' * 15, '-' * 15, '-' * 8, '-' * 15 ]
|
|
214
|
-
|
|
215
|
-
puts "%-80s %8s %15.6f %15.6f %8.3f%% %15.8f" % [ 'Total:', total_calls, total_time_elapsed_total, total_run_time, total_percentage, total_average ]
|
|
216
|
-
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
private
|
|
221
|
-
|
|
222
|
-
# Function to hook a method
|
|
223
|
-
# == params
|
|
224
|
-
# base:: Class or Module
|
|
225
|
-
# method_name:: Name of the method
|
|
226
|
-
# method_type:: public, private or static
|
|
227
|
-
# == returns
|
|
228
|
-
def hook_method( base, method_name, method_type )
|
|
229
|
-
|
|
230
|
-
# create only one wrapper for each method
|
|
231
|
-
unless MobyUtil::Hooking.instance.wrapped_methods.has_key?( "#{ base.name }::#{ method_name }" )
|
|
232
|
-
|
|
233
|
-
# evaluate the generated wrapper source code
|
|
234
|
-
eval("base.#{ base.class.name.downcase }_eval( \"#{ make_wrapper( base, method_name.to_s, method_type.to_s )}\" )") if [ Class, Module ].include?( base.class )
|
|
235
|
-
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
nil
|
|
239
|
-
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
# Function to hook static methods for given Class or Module
|
|
243
|
-
# == params
|
|
244
|
-
# base:: Target Class or Module
|
|
245
|
-
# == returns
|
|
246
|
-
def hook_static_methods( _base )
|
|
247
|
-
|
|
248
|
-
if [ Class, Module ].include?( _base.class )
|
|
249
|
-
|
|
250
|
-
_base.singleton_methods( false ).each { | method_name |
|
|
251
|
-
|
|
252
|
-
hook_method( _base, method_name, "static" ) unless @@non_wrappable_methods.include?( method_name )
|
|
253
|
-
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
nil
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
# Function to hook instance methods for given Class or Module
|
|
262
|
-
# == params
|
|
263
|
-
# base:: Target Class or Module
|
|
264
|
-
# == returns
|
|
265
|
-
def hook_instance_methods( _base )
|
|
266
|
-
|
|
267
|
-
if [ Class, Module ].include?( _base.class )
|
|
268
|
-
|
|
269
|
-
{ :public => _base.public_instance_methods( false ), :private => _base.private_instance_methods( false ), :protected => _base.protected_instance_methods( false ) }.each { | method_type, methods |
|
|
270
|
-
|
|
271
|
-
methods.each { | method_name | hook_method( _base, method_name, method_type.to_s ) unless /__wrappee_\d+/i.match( method_name ) }
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
nil
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
# Function to retrieve method path (e.g. Module1::Module2::Class1)
|
|
281
|
-
# == params
|
|
282
|
-
# base:: Target Class or Module
|
|
283
|
-
# == returns
|
|
284
|
-
# String:: Method path
|
|
285
|
-
def method_path( _base )
|
|
286
|
-
|
|
287
|
-
if [ Class, Module ].include?( _base.class )
|
|
288
|
-
|
|
289
|
-
_base.name
|
|
290
|
-
|
|
291
|
-
else
|
|
292
|
-
|
|
293
|
-
_base.class.name
|
|
294
|
-
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
# Function to generate unique name for wrappee method
|
|
300
|
-
# == params
|
|
301
|
-
# method_name:: Name of the target method
|
|
302
|
-
# == returns
|
|
303
|
-
# String:: Unique name for wrappee method
|
|
304
|
-
def create_wrappee_name( method_name )
|
|
305
|
-
|
|
306
|
-
wrappee_name = "non_pritanble_method_name" if ( wrappee_name = ( /[a-z0-9_]*/i.match( method_name ) ) ).length == 0
|
|
307
|
-
|
|
308
|
-
wrappee_name = "__wrappee_#{ @wrappee_count }__#{ wrappee_name }"
|
|
309
|
-
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
# Function for create source code of wrapper for method
|
|
313
|
-
# == params
|
|
314
|
-
# base:: Class or Module
|
|
315
|
-
# method_name:: Name of the method
|
|
316
|
-
# method_type:: public, private or static
|
|
317
|
-
# == returns
|
|
318
|
-
# String:: source code
|
|
319
|
-
def make_wrapper( base, method_name, method_type = nil )
|
|
320
|
-
|
|
321
|
-
# method name with namespace
|
|
322
|
-
base_and_method_name = "#{ base.name }::#{ method_name }"
|
|
323
|
-
|
|
324
|
-
# add method to benchmark table
|
|
325
|
-
@benchmark[ base_and_method_name ] = { :time_elapsed => 0 , :times_called => 0, :time_elapsed_total => 0 } if ENV[ 'TDRIVER_BENCHMARK' ].to_s.downcase == 'true'
|
|
326
|
-
|
|
327
|
-
# create new name for original method
|
|
328
|
-
original_method_name = create_wrappee_name( method_name )
|
|
329
|
-
|
|
330
|
-
# add method to wrapper methods list
|
|
331
|
-
@wrapped_methods.merge!( base_and_method_name => nil )
|
|
332
|
-
@wrappee_count += 1
|
|
333
|
-
|
|
334
|
-
case method_type
|
|
335
|
-
|
|
336
|
-
when 'public', 'private', 'static'
|
|
337
|
-
|
|
338
|
-
source = "
|
|
339
|
-
#{
|
|
340
|
-
# this is needed if method is static
|
|
341
|
-
"class << self" if method_type == 'static'
|
|
342
|
-
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
# create a copy of original method
|
|
346
|
-
alias_method :#{ original_method_name }, :#{ method_name }
|
|
347
|
-
|
|
348
|
-
#{
|
|
349
|
-
|
|
350
|
-
if method_type == 'static'
|
|
351
|
-
|
|
352
|
-
# undefine original version if static method
|
|
353
|
-
"self.send( :undef_method, :#{ method_name } )"
|
|
354
|
-
|
|
355
|
-
else
|
|
356
|
-
|
|
357
|
-
# method visiblity unless method type is static
|
|
358
|
-
"#{ method_type }"
|
|
359
|
-
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
def #{ method_name }( *args, &block )
|
|
366
|
-
|
|
367
|
-
# log method call
|
|
368
|
-
$mobyutil_hooking_instance.log( '#{ method_path( base ) }.#{ method_name }', nil )
|
|
369
|
-
|
|
370
|
-
#{
|
|
371
|
-
|
|
372
|
-
if ENV[ 'TDRIVER_BENCHMARK' ].to_s.downcase == 'true'
|
|
373
|
-
|
|
374
|
-
"# store start time for performance measurement
|
|
375
|
-
start_time = Time.now
|
|
376
|
-
|
|
377
|
-
# Time elapsed in sub calls
|
|
378
|
-
$mobyutil_hooking_elapsed_time << 0.0
|
|
379
|
-
|
|
380
|
-
begin
|
|
381
|
-
|
|
382
|
-
# call original method
|
|
383
|
-
result = send(:#{ original_method_name }, *args, &block )
|
|
384
|
-
|
|
385
|
-
rescue Exception => exception
|
|
386
|
-
|
|
387
|
-
raise exception
|
|
388
|
-
|
|
389
|
-
ensure
|
|
390
|
-
|
|
391
|
-
# calculate actual elapsed time, including time elapsed in sub calls
|
|
392
|
-
elapsed_time = ( ( $mobyutil_hooking_last_call_end_time = Time.now ) - start_time )
|
|
393
|
-
|
|
394
|
-
# elapsed time in sub calls
|
|
395
|
-
elapsed_time_in_subcalls = $mobyutil_hooking_elapsed_time.pop || 0
|
|
396
|
-
|
|
397
|
-
# add elapsed time to caller method
|
|
398
|
-
$mobyutil_hooking_elapsed_time[ -1 ] += elapsed_time unless $mobyutil_hooking_elapsed_time.empty?
|
|
399
|
-
|
|
400
|
-
# store performance results to benchmark hash
|
|
401
|
-
$mobyutil_hooking_instance.update_method_benchmark( '#{ base_and_method_name }', elapsed_time_in_subcalls, elapsed_time )
|
|
402
|
-
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
# return results
|
|
406
|
-
result"
|
|
407
|
-
|
|
408
|
-
else
|
|
409
|
-
|
|
410
|
-
"# call original method
|
|
411
|
-
result = send(:#{ original_method_name }, *args, &block )"
|
|
412
|
-
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
private :#{ original_method_name }
|
|
420
|
-
|
|
421
|
-
#{
|
|
422
|
-
|
|
423
|
-
# this is needed if method is static
|
|
424
|
-
"end" if method_type == 'static'
|
|
425
|
-
|
|
426
|
-
}"
|
|
427
|
-
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
end
|
|
431
|
-
|
|
432
|
-
end # Hooking
|
|
433
|
-
|
|
434
|
-
end # MobyUtil
|