super-test 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|