super-test 1.0.9
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.
- checksums.yaml +7 -0
- data/CHANGE.txt +9 -0
- data/README.txt +13 -0
- data/bin/idb +19 -0
- data/bin/ii +113 -0
- data/bin/istart_mock +36 -0
- data/bin/istop_mock +16 -0
- data/bin/kk +181 -0
- data/bin/rubyatp +42 -0
- data/bin/start_mock +36 -0
- data/bin/stop_mock +16 -0
- data/bin/xgo +45 -0
- data/conf/conf.rb +11 -0
- data/conf/db03.yml +31 -0
- data/conf/db13.yml +37 -0
- data/conf/db19.yml +33 -0
- data/conf/online.yml +32 -0
- data/conf/super_test.yml +40 -0
- data/conf/system.yml +26 -0
- data/conf/sz00.yml +31 -0
- data/conf/sz06.yml +34 -0
- data/conf/wise00.yml +11 -0
- data/data/case.house +0 -0
- data/data/char.house +0 -0
- data/data/images/Bluehills.jpg +0 -0
- data/data/images/Sunset.jpg +0 -0
- data/data/images/Waterlilies.jpg +0 -0
- data/data/images/Winter.jpg +0 -0
- data/data/query.house +18595 -0
- data/data/user.house +8 -0
- data/lib/action/module/check_action.rb +58 -0
- data/lib/action/module/cnnt_action.rb +161 -0
- data/lib/action/module/datacenter_action.rb +48 -0
- data/lib/action/module/http_pack_helper.rb +163 -0
- data/lib/action/module/httpserver_action.rb +297 -0
- data/lib/action/module/inc.rb +21 -0
- data/lib/action/module/mcpack_action.rb +57 -0
- data/lib/action/module/sql_action.rb +84 -0
- data/lib/action/module/ssh_action.rb +37 -0
- data/lib/action/system/user_action.rb +180 -0
- data/lib/common/appium_helper.rb +217 -0
- data/lib/common/atp_helper.rb +74 -0
- data/lib/common/atp_report.rb +344 -0
- data/lib/common/data_house.rb +405 -0
- data/lib/common/data_model.rb +87 -0
- data/lib/common/http/assert_helper.rb +343 -0
- data/lib/common/http/fix_hpricot.rb +118 -0
- data/lib/common/http/html_helper.rb +362 -0
- data/lib/common/http/http_helper.rb +469 -0
- data/lib/common/http/multipart.rb +81 -0
- data/lib/common/isandbox_helper.rb +195 -0
- data/lib/common/json_helper.rb +43 -0
- data/lib/common/mock_helper.rb +168 -0
- data/lib/common/mtop_helper.rb +141 -0
- data/lib/common/myconf_helper.rb +49 -0
- data/lib/common/mylog_helper.rb +77 -0
- data/lib/common/pairwise.rb +121 -0
- data/lib/common/query_house.rb +89 -0
- data/lib/common/report_helper.rb +97 -0
- data/lib/common/robot_helper.rb +85 -0
- data/lib/common/socket/check.rb +325 -0
- data/lib/common/socket/conf_modifier.rb +149 -0
- data/lib/common/socket/context.rb +55 -0
- data/lib/common/socket/data.rb +392 -0
- data/lib/common/socket/data_helper.rb +41 -0
- data/lib/common/socket/env.rb +317 -0
- data/lib/common/socket/inc.rb +24 -0
- data/lib/common/socket/log.rb +213 -0
- data/lib/common/socket/log4s.rb +58 -0
- data/lib/common/socket/log_helper.rb +332 -0
- data/lib/common/socket/my_sql.rb +77 -0
- data/lib/common/socket/net.rb +74 -0
- data/lib/common/socket/network.rb +115 -0
- data/lib/common/socket/rlib/conf_modifier.rb +130 -0
- data/lib/common/socket/rlib/data_helper.rb +33 -0
- data/lib/common/socket/rlib/log_helper.rb +303 -0
- data/lib/common/socket/rlib/process_helper.rb +91 -0
- data/lib/common/socket/stub.rb +276 -0
- data/lib/common/socket/util.rb +266 -0
- data/lib/patterns/inc.rb +10 -0
- data/lib/patterns/mc_base_pattern.rb +474 -0
- data/lib/patterns/some_pattern.rb +145 -0
- data/lib/super_test.rb +114 -0
- data/log/super_test.log +0 -0
- data/log/super_test.log.wf +0 -0
- data/test/cover_me.rb +6 -0
- data/tool/jenny +0 -0
- data/tool/mcsend/mcsend2 +0 -0
- data/tool/mcsend/mcsend2_shead +0 -0
- data/tool/mcserver/conf/mcserver.conf +77 -0
- data/tool/mcserver/conf/mcserverauthip +17 -0
- data/tool/mcserver/mcserver +0 -0
- data/tool/mcserver/mcserver_trans +0 -0
- data/tool/mysql +0 -0
- data/tool/net/mcsend/mcsend +0 -0
- data/tool/net/mcsend/mcsend_trans +0 -0
- data/tool/net/mcsend/nshead.data +7 -0
- data/tool/net/mcsend/res_nshead.data +7 -0
- data/tool/net/my_client/my_client +0 -0
- data/tool/net/tsclient/client.tcl +205 -0
- data/tool/others/kk +190 -0
- data/tool/others/rubyatp +42 -0
- data/tool/others/supertest_install.sh +34 -0
- data/tool/trip/idb +0 -0
- data/tool/ts-agent/nshead.bft +12 -0
- data/tool/ts-agent/server.conf +10 -0
- data/tool/ts-agent/server.tcl +376 -0
- metadata +275 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
#####################################
|
4
|
+
# File:: atp.rb
|
5
|
+
# Author:: hanyu
|
6
|
+
# Create Date:: Mon Aug 3 23:06:14 CST 2009
|
7
|
+
# Update Date:: Mon Aug 3 23:06:14 CST 2009
|
8
|
+
#####################################
|
9
|
+
|
10
|
+
require "test/unit/testcase"
|
11
|
+
require "test/unit/testresult"
|
12
|
+
require "common/atp_report"
|
13
|
+
|
14
|
+
# 采用动态改变类行为的方式来实现透明插入 atp报表 的功能
|
15
|
+
# 缺点是污染了原始对象 :(
|
16
|
+
module Test
|
17
|
+
module Unit
|
18
|
+
# 一个 TestCase 对应一个 文本case,
|
19
|
+
# 所以改写了 startup 和 shutdown 两个方法
|
20
|
+
#class TestCase
|
21
|
+
# def self.startup
|
22
|
+
# #return unless ENV.key? 'AT_LOGFILE'
|
23
|
+
|
24
|
+
# #if File.exist? ENV['AT_LOGFILE'] and File.new(ENV['AT_LOGFILE']).lines.to_a.size > 6
|
25
|
+
# # Report.re_open
|
26
|
+
# #else
|
27
|
+
# # Report.open
|
28
|
+
# # Report.suiteBegin
|
29
|
+
# #end
|
30
|
+
# #Report.caseBegin self.to_s
|
31
|
+
# ## pass or not
|
32
|
+
# #ENV['PASS_OR_NOT'] = "pass"
|
33
|
+
#
|
34
|
+
# end
|
35
|
+
# def self.shutdown
|
36
|
+
# #return unless ENV.key? 'AT_LOGFILE'
|
37
|
+
|
38
|
+
# ## 如果一切顺利,也要打印一个step ? ...yes
|
39
|
+
# #if ENV['PASS_OR_NOT'] == "pass"
|
40
|
+
# # Report.stepBegin self.to_s
|
41
|
+
# # Report.expect "all",0
|
42
|
+
# # Report.actual "all",0
|
43
|
+
# # Report.stepEnd
|
44
|
+
# #end
|
45
|
+
# #Report.caseEnd
|
46
|
+
# #Report.suiteEnd
|
47
|
+
# #Report.close
|
48
|
+
# end
|
49
|
+
#end
|
50
|
+
|
51
|
+
class TestResult
|
52
|
+
def summary
|
53
|
+
["#{run_count} tests",
|
54
|
+
"#{assertion_count} assertions",
|
55
|
+
*@summary_generators.collect{|generator| send(generator)} ].join(", ") + ", hi atp!"
|
56
|
+
end
|
57
|
+
def notify_fault(fault)
|
58
|
+
@faults << fault
|
59
|
+
notify_listeners(FAULT, fault)
|
60
|
+
|
61
|
+
return unless ENV.key? 'AT_LOGFILE'
|
62
|
+
Report.stepBegin fault.test_name
|
63
|
+
Report.expect "逻辑错误",0
|
64
|
+
Report.actual "逻辑错误",1
|
65
|
+
Report.more fault.short_display,fault.long_display
|
66
|
+
Report.stepEnd
|
67
|
+
# pass or not
|
68
|
+
#ENV['PASS_OR_NOT'] = "not"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
@@ -0,0 +1,344 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
#
|
4
|
+
# author: atd
|
5
|
+
|
6
|
+
|
7
|
+
class Report
|
8
|
+
require 'cgi'
|
9
|
+
require 'base64'
|
10
|
+
require 'pathname'
|
11
|
+
require 'fileutils'
|
12
|
+
|
13
|
+
$logfile_is_existed = 0
|
14
|
+
$at_in_report = 0
|
15
|
+
$at_in_suite = 0
|
16
|
+
$at_in_case = 0
|
17
|
+
$at_in_step = 0
|
18
|
+
|
19
|
+
# 打开报告
|
20
|
+
def self.open(owner=nil,title="No Title",filename="report.xml",encoding="gb2312")
|
21
|
+
#若尚未打开报告
|
22
|
+
if ENV['AT_IN_REPORT']!="1"
|
23
|
+
$logfile_is_existed = 1
|
24
|
+
if ENV['AT_LOGFILE'] == nil
|
25
|
+
path = Pathname.new(filename)
|
26
|
+
filename = "#{Dir.pwd}/#{filename}" if path.relative?
|
27
|
+
FileUtils.mkpath(File.dirname(filename))
|
28
|
+
ENV['AT_LOGFILE'] = filename
|
29
|
+
$logfile_is_existed = 0
|
30
|
+
end
|
31
|
+
# 设置环境变量
|
32
|
+
ENV['AT_IN_SUITE'] = nil
|
33
|
+
ENV['AT_IN_CASE'] = nil
|
34
|
+
ENV['AT_IN_STEP'] = nil
|
35
|
+
ENV['AT_IN_REPORT']="1"
|
36
|
+
|
37
|
+
if owner.nil?
|
38
|
+
if ENV['OS'] =~ /windows/i
|
39
|
+
owner = "#{ENV['USERNAME']}@#{ENV['COMPUTERNAME']}"
|
40
|
+
else
|
41
|
+
owner = "#{ENV['USER']}@#{ENV['HOSTNAME']}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
File.open(ENV['AT_LOGFILE'],'w') do |f|
|
46
|
+
f.write <<-endblock
|
47
|
+
<?xml version="1.0" encoding="#{encoding}"?>
|
48
|
+
<report>
|
49
|
+
<schemaversion>2.0.0</schemaversion>
|
50
|
+
<owner>#{owner}</owner>
|
51
|
+
<title>#{CGI::escapeHTML(title)}</title>
|
52
|
+
<s>#{Time.now.to_i}</s>
|
53
|
+
endblock
|
54
|
+
end
|
55
|
+
#若已经打开报告
|
56
|
+
else
|
57
|
+
$at_in_report = 1
|
58
|
+
$at_in_suite = ENV['AT_IN_SUITE'].to_i if ENV['AT_IN_SUITE'] != nil
|
59
|
+
$at_in_case = ENV['AT_IN_CASE'].to_i if ENV['AT_IN_CASE'] != nil
|
60
|
+
$at_in_step = ENV['AT_IN_STEP'].to_i if ENV['AT_IN_STEP'] != nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# 关闭报告
|
65
|
+
def self.close
|
66
|
+
# 恢复成打开报告前的状态
|
67
|
+
suite_level = 0
|
68
|
+
case_level = 0
|
69
|
+
step_level = 0
|
70
|
+
|
71
|
+
step_level = ENV['AT_IN_STEP'].to_i if ENV['AT_IN_STEP'] != nil
|
72
|
+
if $at_in_step < step_level
|
73
|
+
self.stepEnd
|
74
|
+
elsif $at_in_step > step_level
|
75
|
+
self.stepBegin
|
76
|
+
end
|
77
|
+
|
78
|
+
case_level = ENV['AT_IN_CASE'].to_i if ENV['AT_IN_CASE'] != nil
|
79
|
+
if $at_in_case < case_level
|
80
|
+
self.caseEnd
|
81
|
+
elsif $at_in_case > case_level
|
82
|
+
self.caseBegin
|
83
|
+
end
|
84
|
+
|
85
|
+
suite_level = ENV['AT_IN_SUITE'].to_i if ENV['AT_IN_SUITE'] != nil
|
86
|
+
while $at_in_suite < suite_level
|
87
|
+
self.suiteEnd
|
88
|
+
suite_level -= 1
|
89
|
+
end
|
90
|
+
while $at_in_suite > suite_level
|
91
|
+
self.suiteBegin
|
92
|
+
suite_level += 1
|
93
|
+
end
|
94
|
+
|
95
|
+
#若尚未关闭报告
|
96
|
+
if ENV['AT_IN_REPORT']=="1" and $at_in_report == 0
|
97
|
+
_append("<f>#{Time.now.to_i}</f>\n</report>\n")
|
98
|
+
ENV['AT_IN_REPORT'] = nil
|
99
|
+
ENV['AT_LOGFILE'] = nil if $logfile_is_existed == 0
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# add by hanyu
|
104
|
+
def self.re_open
|
105
|
+
#去除末尾4行
|
106
|
+
lines = nil
|
107
|
+
File.open ENV['AT_LOGFILE'],"r" do |file|
|
108
|
+
lines = file.readlines
|
109
|
+
lines = lines[0,lines.size-2]
|
110
|
+
end
|
111
|
+
|
112
|
+
File.open ENV['AT_LOGFILE'],"w" do |file|
|
113
|
+
file.puts lines
|
114
|
+
end
|
115
|
+
|
116
|
+
ENV['AT_IN_REPORT'] = "1"
|
117
|
+
ENV['AT_IN_SUITE'] = "1"
|
118
|
+
end
|
119
|
+
|
120
|
+
# 进入Suite
|
121
|
+
def self.suiteBegin(title="No Title")
|
122
|
+
if ENV['AT_IN_REPORT']== nil
|
123
|
+
self.open()
|
124
|
+
end
|
125
|
+
if ENV['AT_IN_CASE']=="1"
|
126
|
+
self.caseEnd
|
127
|
+
end
|
128
|
+
title = "No Title" if title.length == 0
|
129
|
+
|
130
|
+
if title.include? "/"
|
131
|
+
if ! title.include? ":"
|
132
|
+
print "absolute suite syntax error: #{title}\n"
|
133
|
+
return 1
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
title = CGI::escapeHTML(title)
|
138
|
+
_append("<suite title=\"#{title}\">\n<s>#{Time.now.to_i}</s>\n")
|
139
|
+
t=ENV['AT_IN_SUITE'].to_i
|
140
|
+
t+=1
|
141
|
+
ENV['AT_IN_SUITE']=t.to_s
|
142
|
+
end
|
143
|
+
|
144
|
+
# 结束Suite
|
145
|
+
def self.suiteEnd
|
146
|
+
t = ENV['AT_IN_SUITE'].to_i
|
147
|
+
if t > 0
|
148
|
+
if ENV['AT_IN_CASE']=="1"
|
149
|
+
self.caseEnd
|
150
|
+
end
|
151
|
+
_append("<f>#{Time.now.to_i}</f>\n</suite>\n")
|
152
|
+
if t > 1
|
153
|
+
ENV['AT_IN_SUITE'] = (t - 1).to_s
|
154
|
+
else
|
155
|
+
ENV['AT_IN_SUITE'] = nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# 进入Case
|
161
|
+
def self.caseBegin(title="No Title", id="")
|
162
|
+
if ENV['AT_IN_CASE']=="1"
|
163
|
+
self.caseEnd
|
164
|
+
end
|
165
|
+
|
166
|
+
if ENV['AT_IN_SUITE']==nil
|
167
|
+
if self.suiteBegin(title) == 1
|
168
|
+
return 1
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
title = "No Title" if title.length == 0
|
173
|
+
title = CGI::escapeHTML(title)
|
174
|
+
if id.length > 0
|
175
|
+
_append("<case title=\"#{title}\" id=\"#{id}\">\n<s>#{Time.now.to_i}</s>\n")
|
176
|
+
else
|
177
|
+
_append("<case title=\"#{title}\">\n<s>#{Time.now.to_i}</s>\n")
|
178
|
+
end
|
179
|
+
ENV['AT_IN_CASE']="1"
|
180
|
+
end
|
181
|
+
|
182
|
+
# 结束Case
|
183
|
+
def self.caseEnd
|
184
|
+
if ENV['AT_IN_CASE']=="1"
|
185
|
+
if ENV['AT_IN_STEP']=="1"
|
186
|
+
self.stepEnd
|
187
|
+
end
|
188
|
+
|
189
|
+
_append("<f>#{Time.now.to_i}</f>\n</case>\n")
|
190
|
+
ENV['AT_IN_CASE']= nil
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# 进入Step
|
195
|
+
def self.stepBegin(title="No Title")
|
196
|
+
if ENV['AT_IN_STEP']=="1"
|
197
|
+
self.stepEnd
|
198
|
+
end
|
199
|
+
|
200
|
+
if ENV['AT_IN_CASE']==nil
|
201
|
+
if self.caseBegin(title) == 1
|
202
|
+
return 1
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
title = "No Title" if title.length == 0
|
207
|
+
title = CGI::escapeHTML(title)
|
208
|
+
_append("<step title=\"#{title}\">\n<s>#{Time.now.to_i}</s>\n")
|
209
|
+
ENV['AT_IN_STEP']="1"
|
210
|
+
end
|
211
|
+
|
212
|
+
# 结束Step
|
213
|
+
def self.stepEnd
|
214
|
+
if ENV['AT_IN_STEP']=="1"
|
215
|
+
_append("<f>#{Time.now.to_i}</f>\n</step>\n")
|
216
|
+
ENV['AT_IN_STEP']=nil
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# 指定预期输出
|
221
|
+
def self.expect(title,value,filetype=nil)
|
222
|
+
if ENV['AT_IN_STEP']!="1"
|
223
|
+
self.stepBegin()
|
224
|
+
end
|
225
|
+
value = value.to_s
|
226
|
+
#Tclerk.trace "Report Expect [#{title}], value=[#{value}] and filetype is [#{filetype}]"
|
227
|
+
title = "No Title" if title.length == 0
|
228
|
+
title = CGI::escapeHTML(title)
|
229
|
+
if filetype.nil?
|
230
|
+
_append("<e title=\"#{title}\" type=\"text/plain\">\n#{Base64.encode64(value)}</e>\n")
|
231
|
+
else
|
232
|
+
# 测试文件存在与否
|
233
|
+
if File.file? value
|
234
|
+
content = IO.read(value)
|
235
|
+
_append("<e title=\"#{title}\" type=\"#{filetype}\">\n#{Base64.encode64(content)}</e>\n")
|
236
|
+
else
|
237
|
+
print "Error: Expect file not exists!\n"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# 指定实际输出
|
243
|
+
def self.actual(title,value,filetype=nil)
|
244
|
+
if ENV['AT_IN_STEP']!="1"
|
245
|
+
self.stepBegin()
|
246
|
+
end
|
247
|
+
value = value.to_s
|
248
|
+
#Tclerk.trace "Report Actual [#{title}], value=[#{value}] and filetype is [#{filetype}]"
|
249
|
+
title = "No Title" if title.length == 0
|
250
|
+
title = CGI::escapeHTML(title)
|
251
|
+
if filetype.nil?
|
252
|
+
_append("<a title=\"#{title}\" type=\"text/plain\">\n#{Base64.encode64(value)}</a>\n")
|
253
|
+
else
|
254
|
+
# 测试文件存在与否
|
255
|
+
if File.file? value
|
256
|
+
content = IO.read(value)
|
257
|
+
_append("<a title=\"#{title}\" type=\"#{filetype}\">\n#{Base64.encode64(content)}</a>\n")
|
258
|
+
else
|
259
|
+
print "Error: Actual file not exists!\n"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
def self.assertTrue(title,cond)
|
264
|
+
stepBegin(title)
|
265
|
+
expect(title,true.to_s)
|
266
|
+
actual(title,cond.to_s)
|
267
|
+
stepEnd
|
268
|
+
end
|
269
|
+
|
270
|
+
# 判断返回值
|
271
|
+
def self.assertReturn(title,erc=0,act=nil)
|
272
|
+
act ||= $?.to_s
|
273
|
+
act = act.to_s
|
274
|
+
erc = erc.to_s
|
275
|
+
stepBegin(title)
|
276
|
+
expect("返回值",erc)
|
277
|
+
actual("返回值",act)
|
278
|
+
stepEnd
|
279
|
+
end
|
280
|
+
|
281
|
+
# 其他附件信息
|
282
|
+
def self.more(title,value,filetype=nil)
|
283
|
+
if ENV['AT_IN_REPORT']== nil
|
284
|
+
self.open()
|
285
|
+
end
|
286
|
+
value = value.to_s
|
287
|
+
#Tclerk.trace "{report} More [#{title}], value=[#{value}] and filetype is [#{filetype}]"
|
288
|
+
title = "No Title" if title.length == 0
|
289
|
+
title = CGI::escapeHTML(title)
|
290
|
+
if filetype.nil?
|
291
|
+
_append("<more title=\"#{title}\" type=\"text/plain\">\n#{Base64.encode64(value)}</more>\n")
|
292
|
+
else
|
293
|
+
# 测试文件存在与否
|
294
|
+
if File.file? value
|
295
|
+
content = IO.read(value)
|
296
|
+
_append("<more title=\"#{title}\" type=\"#{filetype}\">\n#{Base64.encode64(content)}</more>\n")
|
297
|
+
else
|
298
|
+
print "Error: More file not exists!\n"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# 为了兼容,定义一堆别名
|
304
|
+
def suite_begin(title="No Title")
|
305
|
+
Report.suiteEnd(title)
|
306
|
+
end
|
307
|
+
def suite_end
|
308
|
+
Report.suiteEnd
|
309
|
+
end
|
310
|
+
def case_begin(title="No Title")
|
311
|
+
Report.caseBegin(title)
|
312
|
+
end
|
313
|
+
def case_end
|
314
|
+
Report.caseEnd
|
315
|
+
end
|
316
|
+
def step_begin(title="No Title")
|
317
|
+
Report.stepBegin(title)
|
318
|
+
end
|
319
|
+
def step_end
|
320
|
+
Report.stepEnd
|
321
|
+
end
|
322
|
+
def assert_true(title,cond)
|
323
|
+
Report.assertTrue(title,cond)
|
324
|
+
end
|
325
|
+
def assert_return(title,erc=0,act=nil)
|
326
|
+
Report.assertReturn(title,erc,act)
|
327
|
+
end
|
328
|
+
def expect(title="No Title",value="",filetype=nil)
|
329
|
+
Report.expect(title,value,filetype)
|
330
|
+
end
|
331
|
+
def actual(title="No Title",value="",filetype=nil)
|
332
|
+
Report.actual(title,value,filetype)
|
333
|
+
end
|
334
|
+
def more(title,value="",filetype=nil)
|
335
|
+
Report.more(title,value,filetype)
|
336
|
+
end
|
337
|
+
|
338
|
+
protected
|
339
|
+
|
340
|
+
# 为报告追加一行
|
341
|
+
def self._append(line)
|
342
|
+
File.open(ENV['AT_LOGFILE'],"a"){|f| f << line}
|
343
|
+
end
|
344
|
+
end
|
@@ -0,0 +1,405 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
#
|
4
|
+
# Author:: hanyu
|
5
|
+
# Date:: 2009.5.7
|
6
|
+
|
7
|
+
if __FILE__ == $0
|
8
|
+
$LIB_ROOT = "#{File.dirname(__FILE__)}/.."
|
9
|
+
$TEST_ROOT = "#{$LIB_ROOT}/.."
|
10
|
+
$: << "#{$LIB_ROOT}"
|
11
|
+
require 'common/log_helper'
|
12
|
+
require 'common/config_helper'
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'yaml'
|
16
|
+
|
17
|
+
# 数据仓库基类
|
18
|
+
# - 读取数据仓库文件,如 user.house
|
19
|
+
# - 与当前环境绑定,如先读 user.house.sz00 若失败则再读 user.house
|
20
|
+
class DataHouse
|
21
|
+
def initialize(house_yaml)
|
22
|
+
if File.exist? $WORK_ROOT+ "/data/" +house_yaml + ".house."+ ConfigHelper::CONF["env"]
|
23
|
+
@data_house = YAML.load_file($WORK_ROOT+ "/data/" +house_yaml + ".house."+ ConfigHelper::CONF["env"])
|
24
|
+
$log.info( "load data_house[" + $WORK_ROOT+ "/data/" +house_yaml + ".house."+ ConfigHelper::CONF["env"]+"] success!" )
|
25
|
+
elsif File.exist? $WORK_ROOT+ "/data/" +house_yaml+ ".house"
|
26
|
+
@data_house = YAML.load_file($WORK_ROOT+ "/data/" +house_yaml+ ".house")
|
27
|
+
$log.info( "load data_house[" + $WORK_ROOT+ "/data/" +house_yaml + ".house."+"] success!" )
|
28
|
+
elsif File.exist? $SUPER_ROOT+ "/data/" +house_yaml + ".house."+ ConfigHelper::CONF["env"]
|
29
|
+
@data_house = YAML.load_file($SUPER_ROOT+ "/data/" +house_yaml + ".house."+ ConfigHelper::CONF["env"])
|
30
|
+
$log.info( "load data_house[" + $SUPER_ROOT+ "/data/" +house_yaml + ".house."+ ConfigHelper::CONF["env"]+"] success!" )
|
31
|
+
elsif File.exist? $SUPER_ROOT+ "/data/" +house_yaml+ ".house"
|
32
|
+
@data_house = YAML.load_file($SUPER_ROOT+ "/data/" +house_yaml+ ".house")
|
33
|
+
$log.info( "load data_house[" + $SUPER_ROOT+ "/data/" +house_yaml + ".house."+"] success!" )
|
34
|
+
else
|
35
|
+
raise "no file to load"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# 返回数据仓库的大小
|
40
|
+
def size
|
41
|
+
@data_house.size
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# 用户库
|
47
|
+
# === Example
|
48
|
+
#
|
49
|
+
# require 'data_house'
|
50
|
+
#
|
51
|
+
class UserHouse < DataHouse
|
52
|
+
private_class_method :new
|
53
|
+
@@instance = nil
|
54
|
+
def self.get_instance
|
55
|
+
@@instance = new("user") unless @@instance
|
56
|
+
@@instance
|
57
|
+
end
|
58
|
+
|
59
|
+
# 随机取得一个用户
|
60
|
+
def get_a_nobody
|
61
|
+
@data_house.at rand(@data_house.size)
|
62
|
+
end
|
63
|
+
|
64
|
+
# 根据用户名取用户
|
65
|
+
#
|
66
|
+
# Example:
|
67
|
+
#
|
68
|
+
# user = UserHouse.get_instance.by_name "ruguo"
|
69
|
+
# puts user
|
70
|
+
def get_by_name(name)
|
71
|
+
@data_house.find do |u|
|
72
|
+
u["name"] == name if u.key? "name"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# 根据Tag来取用户,user.house中的多个tag可以用空格来分隔
|
77
|
+
#
|
78
|
+
# Example:
|
79
|
+
#
|
80
|
+
# user = @user_house.by_tag "haha"
|
81
|
+
#
|
82
|
+
# # @user_house在SystemTest的setup中经过初始化
|
83
|
+
# # @user_house = UserHouse.get_instance
|
84
|
+
#
|
85
|
+
# puts user
|
86
|
+
#
|
87
|
+
# # user.house的内容如下
|
88
|
+
# #---
|
89
|
+
# #- name: ruguo
|
90
|
+
# # password: aaaa
|
91
|
+
# # spaceurl: ruguo32
|
92
|
+
# # tag : haha hoho gaga
|
93
|
+
def get_by_tag(tag)
|
94
|
+
@data_house.find do |u|
|
95
|
+
u["tag"].split(/\s+/).include?(tag) if u.key? "tag"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# 特殊字符库
|
102
|
+
#
|
103
|
+
# 由通用测试点库提供相关功能
|
104
|
+
class CharHouse < DataHouse
|
105
|
+
private_class_method :new
|
106
|
+
@@instance = nil
|
107
|
+
def self.get_instance
|
108
|
+
@@instance = new("char") unless @@instance
|
109
|
+
@@instance
|
110
|
+
end
|
111
|
+
|
112
|
+
# 未实现
|
113
|
+
def rand_string(size)
|
114
|
+
#TODO
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# 通用测试点库
|
119
|
+
# liqiang01@baidu.com
|
120
|
+
class CaseHouse < DataHouse
|
121
|
+
private_class_method :new
|
122
|
+
@@instance = nil
|
123
|
+
def self.get_instance
|
124
|
+
@@instance = new("case") unless @@instance
|
125
|
+
@@instance
|
126
|
+
end
|
127
|
+
|
128
|
+
# 功能
|
129
|
+
# 生成随机字符串
|
130
|
+
#
|
131
|
+
# 参数
|
132
|
+
# size: 串的长度
|
133
|
+
# mask: 串的内容,mask是个字符串类型。其中包含一些用于表示字符串类型的字符。
|
134
|
+
# a: 小写字符串
|
135
|
+
# A: 大写字符串
|
136
|
+
# 0: 数字串
|
137
|
+
# $: 特殊字符串
|
138
|
+
# B: 空白字符
|
139
|
+
# mask中字符顺序无关
|
140
|
+
#
|
141
|
+
# 返回
|
142
|
+
# ret字符串
|
143
|
+
#
|
144
|
+
# Example
|
145
|
+
# CaseHouse.get_instance.rand_string(10,"aAB0$")
|
146
|
+
def rand_string(size, mask)
|
147
|
+
charpool=[]
|
148
|
+
if mask.scan("a").size > 0
|
149
|
+
charpool = charpool+("a".."z").to_a
|
150
|
+
end
|
151
|
+
if mask.scan("A").size > 0
|
152
|
+
charpool = charpool+("A".."Z").to_a
|
153
|
+
end
|
154
|
+
if mask.scan("0").size > 0
|
155
|
+
charpool = charpool+("0".."9").to_a
|
156
|
+
end
|
157
|
+
if mask.scan("$").size > 0
|
158
|
+
charpool = charpool+"~!@#\$%^&*()_+=-{}|\\][:\"';<>?/.,".split(//)
|
159
|
+
end
|
160
|
+
if mask.scan("B").size > 0
|
161
|
+
charpool = charpool+[" "," ","
|
162
|
+
end
|
163
|
+
ret=""
|
164
|
+
1.upto(size){|i|
|
165
|
+
ret << charpool[rand(charpool.size-1)]
|
166
|
+
}
|
167
|
+
return ret
|
168
|
+
end
|
169
|
+
|
170
|
+
# 功能:
|
171
|
+
# 产生8,16,32,64位数字的所有边界值
|
172
|
+
#
|
173
|
+
# 参数:
|
174
|
+
# 无
|
175
|
+
#
|
176
|
+
# 返回:
|
177
|
+
# ret数字的数组
|
178
|
+
#
|
179
|
+
# Example:
|
180
|
+
# CaseHouse.get_instance.get_all_number
|
181
|
+
def get_all_number
|
182
|
+
return [-18446744073709551616, -18446744073709551615, -9223372036854775808, -9223372036854775807, -4294967296, -4294967295, -2147483648, -2147483647, -65536,-65535, -32768, -32767, -256, -255, -1, 0, 1, 255, 256, 32767, 32768, 65535, 65536, 2147483647, 2147483648, 4294967295, 4294967296, 9223372036854775807, 9223372036854775808, 18446744073709551615, 18446744073709551616]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
# 模块库
|
188
|
+
# liqiang01@baidu.com
|
189
|
+
#
|
190
|
+
# 模块信息采用的数据结构:
|
191
|
+
=begin
|
192
|
+
{
|
193
|
+
"[模块名称]" => {
|
194
|
+
"host"=>"[ip]",
|
195
|
+
"username"=>"[用户名]",
|
196
|
+
"password"=>"[密码]",
|
197
|
+
"datacenter_rootdir"=>"[数据根目录在数据中心的位置信息,可以在这里对数据进行tag分类]"
|
198
|
+
"testing_rootdir"=>"[数据根目录在测试环境的位置信息]"
|
199
|
+
"subfiles"=>"[数组,需要进行同步的数据文件,其位置在相应的tag分类下]"
|
200
|
+
"subdirs"=>"[数组,需要进行同步的文件夹,其位置在相应的tag分类下]"
|
201
|
+
"dbversion"=>"[数组,需要同步的每个数据库的版本,目前支持 5.1.30|5.22]"
|
202
|
+
"dbname"=>"[数组,需要同步的每个数据库的名字]"
|
203
|
+
"backsql"=>"[数组,需要同步的每个数据库的sql数据文件名]"
|
204
|
+
"depends"=>"[数组,该模块依赖的其他模块,将递归的同步所有依赖模块]"
|
205
|
+
},
|
206
|
+
"[模块名称]" => {
|
207
|
+
...
|
208
|
+
}
|
209
|
+
}
|
210
|
+
注:当不需要同步数据文件的时候,将subs置为空。
|
211
|
+
当不需要同步数据库数据的时候,将dbversion,dbname,backsql置为空。
|
212
|
+
=end
|
213
|
+
# 数据文件示例:
|
214
|
+
=begin
|
215
|
+
- module: ufriend
|
216
|
+
host: 127.0.0.1
|
217
|
+
username: space
|
218
|
+
password: spaceapptest
|
219
|
+
datacenter_rootdir: space
|
220
|
+
testing_rootdir: /home/space/space
|
221
|
+
subfiles: conf/friend.conf
|
222
|
+
subdirs: conf
|
223
|
+
dbversion: 5.1.30
|
224
|
+
dbname: newfriend
|
225
|
+
backsql: friend/friend_new.sql
|
226
|
+
depends: albumlogic
|
227
|
+
=end
|
228
|
+
class ModuleHouse < DataHouse
|
229
|
+
private_class_method :new
|
230
|
+
@@instance = nil
|
231
|
+
def self.get_instance
|
232
|
+
@@instance = new("module") unless @@instance
|
233
|
+
@@instance
|
234
|
+
end
|
235
|
+
|
236
|
+
# 功能:
|
237
|
+
# 根据模块名取模块数据
|
238
|
+
#
|
239
|
+
# 参数:
|
240
|
+
# name - 模块的名字
|
241
|
+
#
|
242
|
+
# Example:
|
243
|
+
# mdl1 = ModuleHouse.get_instance.get_by_name "ufriend"
|
244
|
+
def get_by_name(name)
|
245
|
+
@data_house.find do |u|
|
246
|
+
u["module"] == name if u.key? "module"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# 功能:
|
251
|
+
# 进行数据同步
|
252
|
+
#
|
253
|
+
# 参数
|
254
|
+
# name - 模块的名字
|
255
|
+
#
|
256
|
+
# Example:
|
257
|
+
# ModuleHouse.get_instance.sync "ufriend"
|
258
|
+
def sync(name)
|
259
|
+
dc = DCHouse.get_instance.get_by_name("datacenter1")
|
260
|
+
mdl = ModuleHouse.get_instance.get_by_name(name)
|
261
|
+
if(mdl["host"]==nil || mdl["username"]==nil || mdl["password"]==nil || mdl["datacenter_rootdir"]==nil || mdl["testing_rootdir"]==nil)
|
262
|
+
puts "Uncomplate Module conf file."
|
263
|
+
return
|
264
|
+
end
|
265
|
+
#对每个subs cp,对每个数据库恢复
|
266
|
+
mdl["subfiles"]!=nil && subfiles = mdl["subfiles"].split
|
267
|
+
mdl["subdirs"]!=nil && subdirs = mdl["subdirs"].split
|
268
|
+
mdl["dbversion"]!=nil && dbversion = mdl["dbversion"].split
|
269
|
+
mdl["dbname"]!=nil && dbname = mdl["dbname"].split
|
270
|
+
mdl["backsql"]!=nil && backsql = mdl["backsql"].split
|
271
|
+
mdl["depends"]!=nil && depends = mdl["depends"].split
|
272
|
+
|
273
|
+
# 首先将所有依赖模块递归同步
|
274
|
+
if(depends!=nil)
|
275
|
+
print "#{name} depends === "
|
276
|
+
end
|
277
|
+
depends!=nil && depends.uniq.each{ |depend_module|
|
278
|
+
print " > #{depend_module}"
|
279
|
+
}
|
280
|
+
puts ""
|
281
|
+
depends!=nil && depends.uniq.each{ |depend_module|
|
282
|
+
puts "try to sync depends module: #{depend_module}"
|
283
|
+
ModuleHouse.get_instance.sync "#{depend_module}"
|
284
|
+
}
|
285
|
+
|
286
|
+
# 同步本模块的数据文件
|
287
|
+
subfiles!=nil && subfiles.each{|dir|
|
288
|
+
puts "try to transfer "+dc["host"]+":"+dc["datacenterpath"]+"/"+mdl["datacenter_rootdir"]+"/"+dir+" to "+mdl["host"]+"@"+mdl["testing_rootdir"]+"/"+dir
|
289
|
+
Util.scpfromto dc["host"], dc["datacenterpath"]+"/"+mdl["datacenter_rootdir"]+"/"+dir, mdl["host"], mdl["testing_rootdir"]+"/"+dir, dc["username"], dc["password"], mdl["username"], mdl["password"]
|
290
|
+
}
|
291
|
+
subdirs!=nil && subdirs.each{|dir|
|
292
|
+
puts "try to transfer "+dc["host"]+":"+dc["datacenterpath"]+"/"+mdl["datacenter_rootdir"]+"/"+dir+" to "+mdl["host"]+"@"+mdl["testing_rootdir"]+"/"+dir
|
293
|
+
Util.scpfromtod dc["host"], dc["datacenterpath"]+"/"+mdl["datacenter_rootdir"]+"/"+dir, mdl["host"], mdl["testing_rootdir"]+"/"+dir, dc["username"], dc["password"], mdl["username"], mdl["password"]
|
294
|
+
}
|
295
|
+
|
296
|
+
# 同步本模块的数据库数据
|
297
|
+
backsql!=nil && backsql.each{|file|
|
298
|
+
if mdl["dbversion"] == "5.1.30"
|
299
|
+
puts "try to #{dc["db01"]["dbpath"]}/bin/mysql -u#{dc["db01"]["dbuser"]} -p#{dc["db01"]["dbpass"]} #{mdl["dbname"]} < #{dc["datacenterpath"]}/#{mdl["backsql"]}"
|
300
|
+
ssh_cmd dc["host"], dc["username"], dc["password"], "#{dc["db01"]["dbpath"]}/bin/mysql -u#{dc["db01"]["dbuser"]} -p#{dc["db01"]["dbpass"]} #{mdl["dbname"]} < #{dc["datacenterpath"]}/#{mdl["backsql"]}"
|
301
|
+
puts Context.get("IOBODY")
|
302
|
+
end
|
303
|
+
if mdl["dbversion"] == "5.22"
|
304
|
+
puts "try to #{dc["db02"]["dbpath"]}/bin/mysql -u#{dc["db02"]["dbuser"]} -p#{dc["db02"]["dbpass"]} #{mdl["dbname"]} < #{dc["datacenterpath"]}/#{mdl["backsql"]}"
|
305
|
+
ssh_cmd dc["host"], dc["username"], dc["password"], "#{dc["db02"]["dbpath"]}/bin/mysql -u#{dc["db02"]["dbuser"]} -p#{dc["db02"]["dbpass"]} #{mdl["dbname"]} < #{dc["datacenterpath"]}/#{mdl["backsql"]}"
|
306
|
+
puts Context.get("IOBODY")
|
307
|
+
end
|
308
|
+
}
|
309
|
+
end
|
310
|
+
|
311
|
+
# 功能:
|
312
|
+
# 进行环境的恢复
|
313
|
+
|
314
|
+
def rollback(name)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# 数据中心库
|
319
|
+
# liqiang01@baidu.com
|
320
|
+
#
|
321
|
+
# 返回一个数据中心的相关数据 datacenter.house
|
322
|
+
# 系统中可以扩充为存在多个数据中心
|
323
|
+
#
|
324
|
+
# 数据中心使用的步骤:
|
325
|
+
=begin
|
326
|
+
=end
|
327
|
+
#
|
328
|
+
# 数据中心采用的数据结构
|
329
|
+
=begin
|
330
|
+
{
|
331
|
+
"datacenter"=>{
|
332
|
+
"host"=>"",
|
333
|
+
"username"=>"",
|
334
|
+
"password"=>"",
|
335
|
+
"datacenterpath"=>"",
|
336
|
+
"db01"=>{
|
337
|
+
"dbpath"=>"",
|
338
|
+
"dbuser"=>"",
|
339
|
+
"dbpass"=>"",
|
340
|
+
"dbport"=>"",
|
341
|
+
},
|
342
|
+
"db02"=>{
|
343
|
+
"dbpath"=>"",
|
344
|
+
"dbuser"=>"",
|
345
|
+
"dbpass"=>"",
|
346
|
+
"dbport"=>""
|
347
|
+
}
|
348
|
+
}
|
349
|
+
}
|
350
|
+
=end
|
351
|
+
# 数据示例:
|
352
|
+
=begin
|
353
|
+
- datacenter: datacenter1
|
354
|
+
host: 10.81.13.169
|
355
|
+
username: space
|
356
|
+
password: spaceapptest
|
357
|
+
datacenterpath: /home/space/datacenter/
|
358
|
+
db01:
|
359
|
+
dbpath: /home/space/database/mysql5.1.30/
|
360
|
+
dbuser: root
|
361
|
+
dbpass: "123456"
|
362
|
+
dbport: "3308"
|
363
|
+
db02:
|
364
|
+
dbpath: /home/space/database/mysql5.22/
|
365
|
+
dbuser: root
|
366
|
+
dbpass: "123456"
|
367
|
+
dbport: "3308"
|
368
|
+
=end
|
369
|
+
class DCHouse < DataHouse
|
370
|
+
private_class_method :new
|
371
|
+
@@instance = nil
|
372
|
+
def self.get_instance
|
373
|
+
@@instance = new("datacenter") unless @@instance
|
374
|
+
@@instance
|
375
|
+
end
|
376
|
+
|
377
|
+
# 功能:
|
378
|
+
# 根据名字获取数据中心的相关信息
|
379
|
+
#
|
380
|
+
# Example:
|
381
|
+
# dc = DCHouse.get_instance.get_by_name("datacenter1")
|
382
|
+
# str = dc["host"]
|
383
|
+
# str = dc["db01"]["dbpath"]
|
384
|
+
def get_by_name(name)
|
385
|
+
@data_house.find do |u|
|
386
|
+
u["datacenter"] == name if u.key? "datacenter"
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
|
392
|
+
|
393
|
+
if __FILE__ == $0
|
394
|
+
class MyTest
|
395
|
+
def test(str)
|
396
|
+
puts str
|
397
|
+
puts str.encoding
|
398
|
+
end
|
399
|
+
end
|
400
|
+
Test.new.test "放了时间来访"
|
401
|
+
p UserHouse.get_instance.one_nobody
|
402
|
+
p UserHouse.get_instance.find_by_name "iii"
|
403
|
+
|
404
|
+
end
|
405
|
+
|