testability-driver 0.9.2 → 1.0.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.
- data/lib/tdriver/base/behaviour/behaviours/object_behaviour_composition.rb +1 -1
- data/lib/tdriver/base/behaviour/behaviours/object_behaviour_description.rb +11 -7
- data/lib/tdriver/base/behaviour/behaviours/object_composition.rb +8 -0
- data/lib/tdriver/base/behaviour/factory.rb +229 -209
- data/lib/tdriver/base/errors.rb +3 -0
- data/lib/tdriver/base/state_object.rb +11 -20
- data/lib/tdriver/base/sut/controller.rb +4 -4
- data/lib/tdriver/base/sut/factory.rb +205 -170
- data/lib/tdriver/base/sut/generic/behaviours/application.rb +256 -174
- data/lib/tdriver/base/sut/generic/behaviours/find.rb +17 -11
- data/lib/tdriver/base/sut/generic/behaviours/flash_behaviour.rb +57 -66
- data/lib/tdriver/base/sut/generic/behaviours/sut.rb +578 -497
- data/lib/tdriver/base/sut/generic/behaviours/switchbox_behaviour.rb +41 -15
- data/lib/tdriver/base/sut/generic/behaviours/verification.rb +48 -19
- data/lib/tdriver/base/sut/generic/commands/fixture.rb +47 -0
- data/lib/tdriver/base/sut/generic/commands/key_sequence.rb +25 -13
- data/lib/tdriver/base/sut/generic/commands/screen_capture.rb +16 -10
- data/lib/tdriver/base/sut/generic/plugin.rb +9 -3
- data/lib/tdriver/base/sut/sut.rb +41 -33
- data/lib/tdriver/base/test_object/abstract.rb +26 -3
- data/lib/tdriver/base/test_object/adapter.rb +399 -0
- data/lib/tdriver/base/test_object/behaviours/syncronization.rb +56 -14
- data/lib/tdriver/base/test_object/behaviours/test_object.rb +663 -197
- data/lib/tdriver/base/test_object/cache.rb +132 -0
- data/lib/tdriver/base/test_object/factory.rb +677 -426
- data/lib/tdriver/base/test_object/factory_new.rb +202 -0
- data/lib/tdriver/base/test_object/identificator.rb +24 -17
- data/lib/tdriver/base/test_object/loader.rb +9 -3
- data/lib/tdriver/base/test_object/verification.rb +181 -0
- data/lib/tdriver/loader.rb +1 -1
- data/lib/tdriver/report/report.rb +2 -0
- data/lib/tdriver/report/report_api.rb +4 -4
- data/lib/tdriver/report/report_creator.rb +29 -3
- data/lib/tdriver/report/report_data_presentation.rb +7 -3
- data/lib/tdriver/report/report_execution_statistics.rb +80 -21
- data/lib/tdriver/report/report_javascript.rb +192 -0
- data/lib/tdriver/report/report_test_case_run.rb +22 -0
- data/lib/tdriver/report/report_test_run.rb +62 -55
- data/lib/tdriver/report/report_writer.rb +57 -56
- data/lib/tdriver/tdriver.rb +14 -41
- data/lib/tdriver/util/common/error.rb +1 -0
- data/lib/tdriver/util/common/exceptions.rb +12 -0
- data/lib/tdriver/util/common/file.rb +12 -6
- data/lib/tdriver/util/common/gem.rb +2 -1
- data/lib/tdriver/util/common/hash.rb +152 -0
- data/lib/tdriver/util/common/kernel.rb +49 -34
- data/lib/tdriver/util/common/loader.rb +21 -17
- data/lib/tdriver/util/common/numeric.rb +39 -0
- data/lib/tdriver/util/common/object.rb +115 -0
- data/lib/tdriver/util/common/string.rb +55 -2
- data/lib/tdriver/util/dbaccess/dbaccess.rb +194 -161
- data/lib/tdriver/util/dynamic_attribute_filter.rb +6 -0
- data/lib/tdriver/util/hooking.rb +2 -2
- data/lib/tdriver/util/loader.rb +2 -2
- data/lib/tdriver/util/localisation/localisation.rb +277 -18
- data/lib/tdriver/util/logger.rb +142 -13
- data/lib/tdriver/util/parameter/parameter_hash.rb +8 -5
- data/lib/tdriver/util/parameter/parameter_xml.rb +18 -2
- data/lib/tdriver/util/recorder.rb +17 -12
- data/lib/tdriver/util/user_data/user_data.rb +3 -2
- data/lib/tdriver/util/{video_rec.rb → video_utils.rb} +136 -16
- data/lib/tdriver/util/xml/abstraction.rb +7 -0
- data/lib/tdriver/util/xml/attribute.rb +32 -0
- data/lib/tdriver/util/xml/loader.rb +8 -2
- data/lib/tdriver/util/xml/nil_node.rb +95 -0
- data/lib/tdriver/util/xml/parsers/nokogiri/abstraction.rb +46 -7
- data/lib/tdriver/util/xml/parsers/nokogiri/attribute.rb +19 -9
- data/lib/tdriver/util/xml/parsers/nokogiri/document.rb +1 -1
- data/lib/tdriver/util/xml/parsers/nokogiri/element.rb +13 -1
- data/lib/tdriver/util/xml/parsers/nokogiri/loader.rb +6 -0
- data/lib/tdriver/util/xml/parsers/nokogiri/nodeset.rb +27 -15
- data/lib/tdriver/util/xml/parsers/nokogiri/text.rb +57 -0
- data/lib/tdriver/util/xml/text.rb +32 -0
- data/lib/tdriver/util/xml/xml.rb +35 -22
- data/lib/tdriver/version.rb +1 -1
- data/lib/tdriver-devtools/behaviour/xml/rdoc_behaviour_xml_generator.rb +41 -34
- data/lib/tdriver-devtools/doc/generate.rb +31 -6
- data/lib/tdriver-devtools/doc/xslt/template.xsl +46 -25
- data/lib/tdriver-devtools/tests/feature_tests/example/behaviour_example.rb +100 -0
- data/lib/tdriver-devtools/tests/feature_tests/update +1 -1
- data/lib/tdriver.rb +0 -3
- data/xml/behaviours/generic.xml +1 -1
- data/xml/defaults/generic.xml +4 -90
- data/xml/templates/generic.xml +33 -25
- metadata +21 -29
- data/lib/tdriver-devtools/behaviour/xml_generator/example/flick-example.rb +0 -245
- data/lib/tdriver-devtools/behaviour/xml_generator/example/sut.rb +0 -964
- data/lib/tdriver-devtools/behaviour/xml_generator/generate.rb +0 -68
- data/lib/tdriver-devtools/behaviour/xml_generator/lib/custom_rdoc_generator.rb +0 -1865
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument.default.template +0 -1
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument.template +0 -3
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument_type.template +0 -4
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.exception.template +0 -4
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.arguments.template +0 -4
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.deprecated.template +0 -3
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.exceptions.template +0 -3
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.info.template +0 -1
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.returns.template +0 -3
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.tables.template +0 -3
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.template +0 -12
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.returns.template +0 -5
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.item.template +0 -1
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.row.template +0 -2
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.template +0 -7
- data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.template +0 -14
- data/lib/tdriver-devtools/behaviour/xml_generator/update +0 -3
- data/lib/tdriver-devtools/tests/feature_tests/example/flick-example.rb +0 -233
- data/lib/tdriver-devtools/tests/feature_tests/example/impl.rb +0 -194
|
@@ -20,20 +20,24 @@
|
|
|
20
20
|
require 'rbconfig' # ??
|
|
21
21
|
|
|
22
22
|
# common modules - should be generic and runnable as standalone
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
[
|
|
24
|
+
# Ruby object extensions
|
|
25
|
+
'object.rb',
|
|
26
|
+
'numeric.rb',
|
|
27
|
+
'hash.rb',
|
|
28
|
+
'string.rb',
|
|
29
|
+
|
|
30
|
+
'exceptions.rb',
|
|
31
|
+
'error.rb', # TODO: move custom exceptions to exceptions.rb
|
|
32
|
+
|
|
33
|
+
'array.rb',
|
|
34
|
+
'crc16.rb',
|
|
35
|
+
'environment.rb',
|
|
36
|
+
'file.rb',
|
|
37
|
+
'gem.rb',
|
|
38
|
+
'kernel.rb',
|
|
39
|
+
'retryable.rb' ].each{ | filename |
|
|
40
|
+
|
|
41
|
+
require File.expand_path( File.join( File.dirname( __FILE__ ), filename ) )
|
|
42
|
+
|
|
43
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
# extend Ruby Numeric class functionality
|
|
21
|
+
class Numeric
|
|
22
|
+
|
|
23
|
+
def positive?
|
|
24
|
+
self > 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def non_negative?
|
|
28
|
+
self >= 0
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def non_positive?
|
|
32
|
+
self <= 0
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def negative?
|
|
36
|
+
self < 0
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
# extend Ruby Object class functionality
|
|
21
|
+
class Object
|
|
22
|
+
|
|
23
|
+
# define method to class instance
|
|
24
|
+
def meta_def method_name, &block
|
|
25
|
+
|
|
26
|
+
( class << self; self; end ).instance_eval{ define_method method_name, &block }
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Compare receiver object type with given types. Raises exception is class name does not equal.
|
|
31
|
+
def check_type( types, message = "wrong argument type $1 (expected $2)" )
|
|
32
|
+
|
|
33
|
+
# raise exception if message is not type of String
|
|
34
|
+
raise TypeError.new( "wrong argument type %s for message (expected String)" % [ message.class ] ) unless message.kind_of?( String )
|
|
35
|
+
|
|
36
|
+
# create array of types
|
|
37
|
+
type_array = types.kind_of?( Array ) ? types : [ types ]
|
|
38
|
+
|
|
39
|
+
# default result value
|
|
40
|
+
found = false
|
|
41
|
+
|
|
42
|
+
# collect verbose type list
|
|
43
|
+
verbose_type_list = type_array.each_with_index.collect{ | type, index |
|
|
44
|
+
|
|
45
|
+
raise TypeError.new( "invalid argument type #{ type } for check_type. Did you mean #{ type.class }?" ) unless type.kind_of?( Class )
|
|
46
|
+
|
|
47
|
+
found = true if self.kind_of?( type )
|
|
48
|
+
|
|
49
|
+
# result string, separate types if multiple types given
|
|
50
|
+
"#{ ( ( index > 0 ) ? ( index + 1 < type_array.count ? ", " : " or " ) : "" ) }#{ type.to_s }"
|
|
51
|
+
|
|
52
|
+
}.join
|
|
53
|
+
|
|
54
|
+
# raise exception if type did not match
|
|
55
|
+
unless found
|
|
56
|
+
|
|
57
|
+
# convert macros
|
|
58
|
+
[ self.class, verbose_type_list, self.inspect ].each_with_index{ | param, index | message.gsub!( "$#{ index + 1 }", param.to_s ) }
|
|
59
|
+
|
|
60
|
+
# raise the exception
|
|
61
|
+
raise TypeError.new( message )
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# pass self as return value
|
|
66
|
+
self
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def not_nil( message = "Value must not be nil", exception = ArgumentError )
|
|
71
|
+
|
|
72
|
+
raise exception.new( message ) if self.nil?
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def validate( values, message = "Unexpected value $3 for $1 (expected $2)" )
|
|
77
|
+
|
|
78
|
+
# raise exception if message is not type of String
|
|
79
|
+
raise TypeError.new( "wrong argument type %s for message (expected String)" % [ message.class ] ) unless message.kind_of?( String )
|
|
80
|
+
|
|
81
|
+
# create array of values
|
|
82
|
+
values_array = values.kind_of?( Array ) ? values : [ values ]
|
|
83
|
+
|
|
84
|
+
# default result value
|
|
85
|
+
found = false
|
|
86
|
+
|
|
87
|
+
# collect verbose type list
|
|
88
|
+
verbose_values_list = values_array.each_with_index.collect{ | value, index |
|
|
89
|
+
|
|
90
|
+
raise TypeError.new( "Invalid argument type #{ value.class } for value (expected #{ self.class })" ) unless value.kind_of?( self.class )
|
|
91
|
+
|
|
92
|
+
found = true if self == value
|
|
93
|
+
|
|
94
|
+
# result string, separate types if multiple types given
|
|
95
|
+
"#{ ( ( index > 0 ) ? ( index + 1 < values_array.count ? ", " : " or " ) : "" ) }#{ value.inspect }"
|
|
96
|
+
|
|
97
|
+
}.join
|
|
98
|
+
|
|
99
|
+
# raise exception if value was not found
|
|
100
|
+
unless found
|
|
101
|
+
|
|
102
|
+
# convert macros
|
|
103
|
+
[ self.class, verbose_values_list, self.inspect ].each_with_index{ | param, index | message.gsub!( "$#{ index + 1 }", param.to_s ) }
|
|
104
|
+
|
|
105
|
+
# raise the exception
|
|
106
|
+
raise ArgumentError.new( message )
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# pass self as return value
|
|
111
|
+
self
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
@@ -17,6 +17,58 @@
|
|
|
17
17
|
##
|
|
18
18
|
############################################################################
|
|
19
19
|
|
|
20
|
+
class String
|
|
21
|
+
|
|
22
|
+
def not_empty( message = "String must not be empty", exception = ArgumentError )
|
|
23
|
+
|
|
24
|
+
raise exception.new( message ) if self.empty?
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Function determines if string is "true" or "false"
|
|
29
|
+
# == params
|
|
30
|
+
# string:: String
|
|
31
|
+
# == returns
|
|
32
|
+
# TrueClass/FalseClass
|
|
33
|
+
def boolean?
|
|
34
|
+
|
|
35
|
+
/^(true|false)$/i.match( self ).kind_of?( MatchData )
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Function determines if string is numeric
|
|
40
|
+
# == params
|
|
41
|
+
# string:: Numeric string
|
|
42
|
+
# == returns
|
|
43
|
+
# TrueClass/FalseClass
|
|
44
|
+
def numeric?
|
|
45
|
+
|
|
46
|
+
/^[0-9]+$/.match( self ).kind_of?( MatchData )
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Function converts "true" or "false" to boolean
|
|
51
|
+
# == params
|
|
52
|
+
# string:: String
|
|
53
|
+
# == returns
|
|
54
|
+
# TrueClass/FalseClass
|
|
55
|
+
def to_boolean
|
|
56
|
+
|
|
57
|
+
if /^(true|false)$/i.match( self.to_s )
|
|
58
|
+
|
|
59
|
+
$1.downcase == 'true'
|
|
60
|
+
|
|
61
|
+
else
|
|
62
|
+
|
|
63
|
+
#default
|
|
64
|
+
Kernel::raise TypeError.new( "Unable to convert string \"#{ self }\" to boolean (Expected \”true\" or \"false\")" )
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
20
72
|
module MobyUtil
|
|
21
73
|
|
|
22
74
|
class StringHelper
|
|
@@ -29,7 +81,8 @@ module MobyUtil
|
|
|
29
81
|
def self.boolean?( string )
|
|
30
82
|
|
|
31
83
|
# raise exception if argument type other than String
|
|
32
|
-
Kernel::raise ArgumentError.new("Invalid argument format %s (Expected: %s)" % [ string.class, "String" ]) unless string.kind_of?( String )
|
|
84
|
+
#Kernel::raise ArgumentError.new("Invalid argument format %s (Expected: %s)" % [ string.class, "String" ]) unless string.kind_of?( String )
|
|
85
|
+
string.check_type( String, "Wrong argument type $1 (Expected $2)" )
|
|
33
86
|
|
|
34
87
|
/^(true|false)$/i.match( string ).kind_of?( MatchData )
|
|
35
88
|
|
|
@@ -46,7 +99,7 @@ module MobyUtil
|
|
|
46
99
|
|
|
47
100
|
Kernel::raise ArgumentError.new("Invalid argument format %s (Expected: %s)" % [ string.class, "String" ]) unless string.kind_of?( String )
|
|
48
101
|
|
|
49
|
-
|
|
102
|
+
/^[0-9]+$/.match( string ).kind_of?( MatchData )
|
|
50
103
|
|
|
51
104
|
end
|
|
52
105
|
|
|
@@ -18,171 +18,204 @@
|
|
|
18
18
|
############################################################################
|
|
19
19
|
|
|
20
20
|
# Utility for handling database connections
|
|
21
|
-
|
|
22
21
|
module MobyUtil
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
class DBAccess
|
|
25
24
|
|
|
26
25
|
DB_TYPE_MYSQL = 'mysql'
|
|
27
26
|
DB_TYPE_SQLITE = 'sqlite'
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
28
|
+
include Singleton
|
|
29
|
+
|
|
30
|
+
# == description
|
|
31
|
+
# Initialize the singleton
|
|
32
|
+
# connection is maintained as long as the connectivity parameters remain the same
|
|
33
|
+
# this is to avoid constant connect as this takes time
|
|
34
|
+
#
|
|
35
|
+
def initialize
|
|
36
|
+
@@_connections = {}
|
|
37
|
+
@@_mysql = nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# == description
|
|
41
|
+
# Class Method that returns existing connections
|
|
42
|
+
#
|
|
43
|
+
def DBAccess.connections()
|
|
44
|
+
return @@_connections
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# == description
|
|
48
|
+
# Runs an SQL query on the on the given MobyUtil::DBConnection
|
|
49
|
+
#
|
|
50
|
+
# == arguments
|
|
51
|
+
# dbc
|
|
52
|
+
# MobyUtil::DBConnection
|
|
53
|
+
# description: object with the connection details of an open sql connection
|
|
54
|
+
#
|
|
55
|
+
# query_string
|
|
56
|
+
# String
|
|
57
|
+
# description: database-specific SQL query (note that mysql and sqlite have slightly different syntax)
|
|
58
|
+
# example: "select * from tdriver_locale;"
|
|
59
|
+
#
|
|
60
|
+
# == returns
|
|
61
|
+
# Array
|
|
62
|
+
# description: Array of rows returned by the server. Each row is an array of String values.
|
|
63
|
+
#
|
|
64
|
+
# == throws
|
|
65
|
+
# ArgumentError
|
|
66
|
+
# description: if the argument provided is not the right object type
|
|
67
|
+
#
|
|
68
|
+
def self.query( dbc, query_string )
|
|
69
|
+
# Create first instance of this class if it doesn't exist
|
|
70
|
+
self.instance
|
|
71
|
+
|
|
72
|
+
#raise ArgumentError.new("Invalid connection object provided.") if dbc.nil? or !dbc.kind_of? MobyUtil::DBConnection
|
|
73
|
+
dbc.check_type( MobyUtil::DBConnection, "Wrong argument type $1 for database connection object (expected $2)" )
|
|
74
|
+
|
|
75
|
+
#raise ArgumentError.new("The query qtring must be provided as a non empty string.") if query_string.nil? or query_string.class != String or query_string.empty?
|
|
76
|
+
query_string.check_type( String, "Wrong variable type $1 for database query string (expected $2)")
|
|
77
|
+
query_string.not_empty( "Database query string must not be empty string" )
|
|
78
|
+
|
|
79
|
+
db_type = dbc.db_type
|
|
80
|
+
host = dbc.host
|
|
81
|
+
username = dbc.username
|
|
82
|
+
password = dbc.password
|
|
83
|
+
database_name = dbc.database_name
|
|
84
|
+
|
|
85
|
+
# Check creation parameters
|
|
86
|
+
|
|
87
|
+
#raise DbTypeNotDefinedError.new( "Database type need to be either 'mysql' or 'sqlite'!" ) if db_type == nil
|
|
88
|
+
db_type.check_type( String, "Wrong argument type $1 for database type (expected $2)" )
|
|
89
|
+
|
|
90
|
+
#raise DbTypeNotSupportedError.new( "Database type '#{db_type}' not supported! Type need to be either 'mysql' or 'sqlite'!" ) unless db_type == DB_TYPE_MYSQL or db_type == DB_TYPE_SQLITE
|
|
91
|
+
db_type.validate( [ DB_TYPE_MYSQL, DB_TYPE_SQLITE ], "Unsupported database type $1 (expected $2)" )
|
|
92
|
+
|
|
93
|
+
if ( db_type == DB_TYPE_MYSQL )
|
|
94
|
+
|
|
95
|
+
# raise ArgumentError.new("Host must be provided as a non empty string.") if host.nil? or host.class != String or host.empty?
|
|
96
|
+
host.check_type( String, "Wrong variable type $1 for host (expected $2)" )
|
|
97
|
+
host.not_empty( "Host must not be empty string" )
|
|
98
|
+
|
|
99
|
+
#raise ArgumentError.new("Username must be provided as a non empty string.") if username.nil? or username.class != String or username.empty?
|
|
100
|
+
username.check_type( String, "Wrong variable type $1 for username (expected $2)" )
|
|
101
|
+
username.not_empty( "Username must not be empty string" )
|
|
102
|
+
|
|
103
|
+
#raise ArgumentError.new("Password must be provided as a string.") if password.nil? or password.class != String
|
|
104
|
+
password.check_type( String, "Wrong variable type $1 for password (expected $2)")
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#raise ArgumentError.new("The database name must be provided as a non empty string.") if database_name.nil? or database_name.class != String or database_name.empty?
|
|
109
|
+
database_name.check_type( String, "Wrong variable type $1 for database name (expected $2)" )
|
|
110
|
+
database_name.not_empty( "Database name must not be empty string" )
|
|
111
|
+
|
|
112
|
+
# Check for exsting connection for that host and create it if needed
|
|
113
|
+
if !@@_connections.has_key?( host + db_type + database_name ) # make connection ID unique by using host, type and db on the key
|
|
114
|
+
dbc.dbh = connect_db( db_type, host, username, password, database_name )
|
|
115
|
+
@@_connections[ host + db_type + database_name ] = dbc
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
if db_type == DB_TYPE_MYSQL
|
|
119
|
+
|
|
120
|
+
query_result = @@_connections[ host + db_type + database_name ].dbh.query( query_string ) # identical?
|
|
121
|
+
|
|
122
|
+
elsif dbc.db_type == DB_TYPE_SQLITE
|
|
123
|
+
|
|
124
|
+
query_result = @@_connections[ host + db_type + database_name ].dbh.query( query_string ) # identical?
|
|
125
|
+
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Return a uniform set of results as an array of rows, rows beeing an array of values ( Array<Array<String>> )
|
|
129
|
+
result = []
|
|
130
|
+
|
|
131
|
+
if db_type == DB_TYPE_MYSQL and !query_result.nil?
|
|
132
|
+
|
|
133
|
+
query_result.num_rows.times do |i|
|
|
134
|
+
|
|
135
|
+
result << query_result.fetch_row
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
elsif db_type == DB_TYPE_SQLITE and !query_result.nil?
|
|
140
|
+
|
|
141
|
+
# Create Array<SQLite3::ResultSet::ArrayWithTypesAndFields<String>> type result
|
|
142
|
+
# it effectively behaves the same as with Array<Array<String>> but the inner Arrays have .fields and .types properties
|
|
143
|
+
# which return the column name and type for each value on the row (Array) returned.
|
|
144
|
+
while ( row = query_result.next )
|
|
145
|
+
result << row
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# it is essentially a prepare method so we need to call close to free the connection
|
|
149
|
+
query_result.close
|
|
150
|
+
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
result
|
|
154
|
+
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# == description
|
|
158
|
+
# Retunrs the number of affected rows on the latest sql query on the given MobyUtil::DBConnection
|
|
159
|
+
#
|
|
160
|
+
# == arguments
|
|
161
|
+
# dbc
|
|
162
|
+
# MobyUtil::DBConnection
|
|
163
|
+
# description: object with the connection details of an open sql connection
|
|
164
|
+
#
|
|
165
|
+
# == returns
|
|
166
|
+
# Integer
|
|
167
|
+
# description: number of rows affected
|
|
168
|
+
#
|
|
169
|
+
# == throws
|
|
170
|
+
# ArgumentError
|
|
171
|
+
# description: if the argument provided is not the right object type
|
|
172
|
+
#
|
|
173
|
+
def self.affected_rows(dbc)
|
|
174
|
+
|
|
175
|
+
#raise ArgumentError.new("Invalid connection object provided.") if dbc.nil? or !dbc.kind_of? MobyUtil::DBConnection
|
|
176
|
+
dbc.check_type( MobyUtil::DBConnection, "Wrong argument type $1 for database connection object (expected $2)" )
|
|
177
|
+
|
|
178
|
+
# Check for exsting connection for that host and create it if needed
|
|
179
|
+
if !@@_connections.has_key?( dbc.host + dbc.db_type + dbc.database_name ) # make connection ID unique by using host, type and db on the key
|
|
180
|
+
dbc.dbh = connect_db( dbc.db_type, dbc.host, dbc.username, dbc.password, dbc.database_name )
|
|
181
|
+
@@_connections[ dbc.host + dbc.db_type + dbc.database_name ] = dbc
|
|
182
|
+
end
|
|
183
|
+
result = 0
|
|
184
|
+
if dbc.db_type == DB_TYPE_MYSQL
|
|
185
|
+
result = @@_connections[ dbc.host + dbc.db_type + dbc.database_name ].dbh.affected_rows
|
|
186
|
+
elsif dbc.db_type == DB_TYPE_SQLITE
|
|
187
|
+
result = @@_connections[ dbc.host + dbc.db_type + dbc.database_name ].dbh.changes
|
|
188
|
+
end
|
|
189
|
+
return result
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private
|
|
193
|
+
|
|
194
|
+
# == description
|
|
195
|
+
# Function establishes a new connection to as sql server and returns it's handle
|
|
196
|
+
#
|
|
197
|
+
def self.connect_db( db_type, host, username, password, database_name )
|
|
198
|
+
|
|
199
|
+
# if mysql API and connection are not initialized, then initialize the mysql API
|
|
200
|
+
if ( db_type == DB_TYPE_MYSQL ) && ( @@_mysql.nil? )
|
|
201
|
+
require 'mysql'
|
|
202
|
+
@@_mysql = Mysql::init
|
|
203
|
+
elsif db_type == DB_TYPE_SQLITE
|
|
204
|
+
require 'sqlite3'
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
begin
|
|
208
|
+
dbh = @@_mysql.connect( host, username, password, database_name) if db_type == DB_TYPE_MYSQL
|
|
209
|
+
dbh.query 'SET NAMES utf8' if db_type == DB_TYPE_MYSQL # set the utf8 encoding
|
|
210
|
+
dbh = SQLite3::Database.new( database_name ) if db_type == DB_TYPE_SQLITE
|
|
211
|
+
rescue
|
|
212
|
+
raise SqlConnectError.new( $!.message )
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
return dbh
|
|
216
|
+
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
end # DBAccess
|
|
188
220
|
|
|
221
|
+
end # MobyUtil
|