SurfCustomCalabash 0.2.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +68 -4
- data/SurfCustomCalabash.gemspec +3 -3
- data/bin/SurfCustomCalabash +54 -0
- data/bin/surf-calabash-console.rb +62 -0
- data/bin/surf-calabash-gen.rb +17 -0
- data/bin/surf-calabash-helpers.rb +34 -0
- data/lib/SurfCustomCalabash/CommonMethods.rb +3 -3
- data/lib/SurfCustomCalabash/DroidMethods.rb +2 -1
- data/lib/SurfCustomCalabash/IosMethods.rb +2 -2
- data/lib/SurfCustomCalabash/version.rb +1 -1
- data/sources/Backdoors list b/data/sources/Backdoors → list +0 -0
- data/sources/Gemfile +27 -0
- data/sources/Scripts/and.sh +5 -0
- data/sources/Scripts/ca.sh +5 -0
- data/sources/Scripts/ci.sh +5 -0
- data/sources/Scripts/data +7 -0
- data/sources/Scripts/fa.sh +6 -0
- data/sources/Scripts/fi.sh +5 -0
- data/sources/Scripts/get_apk.rb +68 -0
- data/sources/Scripts/get_scenarios.rb +193 -0
- data/sources/Scripts/import_scenarios.rb +172 -0
- data/sources/Scripts/ios.sh +5 -0
- data/sources/Scripts/parallel_android_smoke.sh +4 -0
- data/sources/Scripts/parallel_android_test.sh +4 -0
- data/sources/Scripts/ra.sh +12 -0
- data/sources/Scripts/ri.sh +9 -0
- data/sources/Scripts/smoke_and.sh +5 -0
- data/sources/Scripts/smoke_ios.sh +5 -0
- data/sources/Scripts/ta.sh +5 -0
- data/sources/Scripts/ti.sh +5 -0
- data/sources/Scripts/to_exec.sh +19 -0
- data/sources/Scripts/update.sh +24 -0
- data/sources/Scripts/update_exec.rb +96 -0
- data/sources/TestFolder/small.gif +0 -0
- data/sources/ci/JenkinsfileUiTestAndroid.groovy +22 -0
- data/sources/ci/JenkinsfileUiTestIos.groovy +23 -0
- data/sources/config/cucumber.yml +24 -0
- data/sources/features/android/pages/standard/DroidCommon.rb +33 -0
- data/sources/features/android/pages/standard/Init_android.rb +8 -0
- data/sources/features/android/pages/test.rb +43 -0
- data/sources/features/android/support/app_life_cycle_hooks.rb +147 -0
- data/sources/features/android/support/log_hooks_and.rb +40 -0
- data/sources/features/android/support/video_hooks_and.rb +110 -0
- data/sources/features/ios/pages/standard/Init_ios.rb +5 -0
- data/sources/features/ios/pages/standard/IosCommon.rb +30 -0
- data/sources/features/ios/pages/test.rb +37 -0
- data/sources/features/ios/support/01_launch.rb +194 -0
- data/sources/features/ios/support/log_hooks_ios.rb +40 -0
- data/sources/features/ios/support/video_hooks_ios.rb +58 -0
- data/sources/features/net/net.rb +28 -0
- data/sources/features/net/screentest_api.rb +186 -0
- data/sources/features/scenarios/eng.feature +8 -0
- data/sources/features/scenarios/rus.feature +8 -0
- data/sources/features/step_definitions/test.rb +43 -0
- data/sources/features/support/credentials.rb +11 -0
- data/sources/features/support/env.rb +8 -0
- data/sources/features/support/hooks.rb +21 -0
- data/sources/features/support/localization.rb +8 -0
- data/sources/find_id.rb +95 -0
- data/sources/group_steps.rb +39 -0
- data/sources/irbrcs/android/irbrc +105 -0
- data/sources/irbrcs/ios/irbrc +132 -0
- data/sources/start.sh +134 -0
- metadata +63 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
echo "введите название фича файла с обновленными тестами из папки features/scenarios/name.feature в формате <name>"
|
4
|
+
echo "enter feature file name with updated tests from dir features/scenarios/name.feature in format <name>"
|
5
|
+
|
6
|
+
read path
|
7
|
+
|
8
|
+
index=0
|
9
|
+
while read line; do
|
10
|
+
array[$index]="$line"
|
11
|
+
index=$(($index+1))
|
12
|
+
done < ./Scripts/data
|
13
|
+
|
14
|
+
first_string="${array[0]}"
|
15
|
+
username=${first_string/login /}
|
16
|
+
|
17
|
+
second_string="${array[1]}"
|
18
|
+
password=${second_string/jira_pass /}
|
19
|
+
|
20
|
+
third_string="${array[2]}"
|
21
|
+
code=${third_string/project_key /}
|
22
|
+
|
23
|
+
|
24
|
+
curl -H "Content-Type: multipart/form-data" -u $username:$password -F "file=@features/scenarios/$path.feature" https://jira.surfstudio.ru/rest/raven/1.0/import/feature?projectKey=$code
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'json'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
|
6
|
+
class Execution
|
7
|
+
|
8
|
+
# path - path to dir with autotests, пример - /Users/user_name/autotests/project-test/
|
9
|
+
def initialize(path)
|
10
|
+
|
11
|
+
# hash with data from file scripts/data
|
12
|
+
@all_data = get_all_data
|
13
|
+
|
14
|
+
# login in jira
|
15
|
+
@login = @all_data['login']
|
16
|
+
|
17
|
+
# pass in jira
|
18
|
+
@password = @all_data['jira_pass']
|
19
|
+
|
20
|
+
# project key
|
21
|
+
@key = @all_data['project_key']
|
22
|
+
|
23
|
+
# path to dir with autotests
|
24
|
+
@path = path
|
25
|
+
|
26
|
+
@auth = 'Basic ' + Base64.encode64( "#{@login}:#{@password}" ).chomp
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor :path
|
30
|
+
|
31
|
+
# read user data from file
|
32
|
+
def get_all_data
|
33
|
+
Hash[*File.read("#{@path}scripts/data").split(/[, \n]+/)]
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_test_execution(test_exec)
|
37
|
+
|
38
|
+
key_arr = []
|
39
|
+
|
40
|
+
for i in 1..2
|
41
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/api/testexec/#{test_exec}/test?page=#{i}"
|
42
|
+
|
43
|
+
response = RestClient.get url, {:Authorization => @auth}
|
44
|
+
# Kernel.puts(response)
|
45
|
+
parse_response = JSON.parse(response.body)
|
46
|
+
|
47
|
+
# Kernel.puts(parse_response)
|
48
|
+
|
49
|
+
parse_response.each do |keys|
|
50
|
+
key_arr << keys['key']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Kernel.puts(key_arr.sort)
|
55
|
+
|
56
|
+
$test_keys = key_arr.sort
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def delete_test_from_execution(test_exec)
|
61
|
+
|
62
|
+
p "Start Delete"
|
63
|
+
# begin
|
64
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/api/testexec/#{test_exec}/test"
|
65
|
+
response = RestClient.post url, {:remove => $test_keys}.to_json,
|
66
|
+
{:Authorization => @auth,
|
67
|
+
content_type: :json,
|
68
|
+
accept: :json}
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_test_to_execution(test_exec)
|
72
|
+
|
73
|
+
p "Start Update"
|
74
|
+
|
75
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/api/testexec/#{test_exec}/test"
|
76
|
+
response = RestClient.post url, {:add => $test_keys}.to_json,
|
77
|
+
{:Authorization => @auth,
|
78
|
+
content_type: :json,
|
79
|
+
accept: :json}
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def update_test_execution(test_exec)
|
84
|
+
get_test_execution(test_exec)
|
85
|
+
begin
|
86
|
+
delete_test_from_execution(test_exec)
|
87
|
+
rescue
|
88
|
+
p "Timeout error"
|
89
|
+
p "Retrying Attempt"
|
90
|
+
delete_test_from_execution(test_exec)
|
91
|
+
end
|
92
|
+
|
93
|
+
add_test_to_execution(test_exec)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
@Library('surf-lib@version-3.0.0-SNAPSHOT') // https://bitbucket.org/surfstudio/jenkins-pipeline-lib/
|
2
|
+
import ru.surfstudio.ci.pipeline.ui_test.UiTestPipelineAndroid
|
3
|
+
|
4
|
+
//init
|
5
|
+
def pipeline = new UiTestPipelineAndroid(this)
|
6
|
+
pipeline.init()
|
7
|
+
|
8
|
+
//configuration
|
9
|
+
pipeline.sourceRepoUrl = "TODO add repo source code app"
|
10
|
+
pipeline.jiraProjectKey = "TODO add key project in jira"
|
11
|
+
pipeline.testBranch = "master" // branch with tests
|
12
|
+
pipeline.defaultTaskKey = "TODO add key test execution in jira" //task for run periodically
|
13
|
+
pipeline.projectForBuild = “TODO add name project for build in jenkins”
|
14
|
+
|
15
|
+
|
16
|
+
//customization
|
17
|
+
pipeline.cronTimeTrigger = "00 02 * * *"
|
18
|
+
pipeline.notificationEnabled = false
|
19
|
+
pipeline.buildGradleTask = "clean assembleQa"
|
20
|
+
|
21
|
+
//run
|
22
|
+
pipeline.run()
|
@@ -0,0 +1,23 @@
|
|
1
|
+
@Library('surf-lib@version-3.0.0-SNAPSHOT') // https://bitbucket.org/surfstudio/jenkins-pipeline-lib/
|
2
|
+
import ru.surfstudio.ci.pipeline.ui_test.UiTestPipelineiOS
|
3
|
+
|
4
|
+
//init
|
5
|
+
def pipeline = new UiTestPipelineiOS(this)
|
6
|
+
pipeline.init()
|
7
|
+
|
8
|
+
//configuration
|
9
|
+
pipeline.sourceRepoUrl = "TODO add repo source code app"
|
10
|
+
pipeline.jiraProjectKey = "TODO add key project in jira"
|
11
|
+
pipeline.testBranch = "master" // branch with tests
|
12
|
+
pipeline.defaultTaskKey = "TODO add key test execution in jira" //task for run periodically
|
13
|
+
pipeline.testDeviceName = "iPhone 11"
|
14
|
+
pipeline.testOSVersion = "com.apple.CoreSimulator.SimRuntime.iOS-13-3"
|
15
|
+
pipeline.testiOSSDK = "iphonesimulator13.2"
|
16
|
+
pipeline.projectForBuild = "test"
|
17
|
+
|
18
|
+
//customization
|
19
|
+
pipeline.cronTimeTrigger = "01 04 * * *"
|
20
|
+
pipeline.notificationEnabled = false
|
21
|
+
|
22
|
+
//run
|
23
|
+
pipeline.run()
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# config/cucumber.yml
|
2
|
+
##YAML Template
|
3
|
+
|
4
|
+
android: PLATFORM=android -r features/support -r features/android/support -r features/android -r features/step_definitions -r features/android/pages -r features/android/pages/standard
|
5
|
+
ios: PLATFORM=ios -r features/support -r features/ios/support -r features/step_definitions -r features/ios/pages
|
6
|
+
<%
|
7
|
+
date = Time.now.strftime('%d_%m-%H:%M:%S')
|
8
|
+
default_report = "./output_#{date}_.html"
|
9
|
+
default_json = "./output_#{date}.json"
|
10
|
+
default_allure = "./output_#{date}.html"
|
11
|
+
default_rerun = "./rerun_#{date}.txt"
|
12
|
+
%>
|
13
|
+
|
14
|
+
common: NO_STOP='1'
|
15
|
+
rerun_out: -f rerun -o ./reports/<%= default_rerun %>
|
16
|
+
html_report: -f html -o ./reports/<%= default_report %>
|
17
|
+
json_report: -f json -o ./reports/<%= ENV['DEVICE_INFO']%>.json
|
18
|
+
json_xray: -f json -o ./reports/<%= ENV['DEVICE_INFO']%>_<%= ENV['ADB_DEVICE_ARG']%>.json
|
19
|
+
|
20
|
+
|
21
|
+
run: -p common -p rerun_out -p html_report -p json_report -p allure_report -p json_xray
|
22
|
+
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'calabash-android'
|
2
|
+
require 'SurfCustomCalabash/DroidMethods'
|
3
|
+
|
4
|
+
class DroidCommon
|
5
|
+
|
6
|
+
# system methods
|
7
|
+
def initialize(driver)
|
8
|
+
@driver = driver
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing (sym, *args, &block)
|
12
|
+
@driver.send sym, *args, &block
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.element(name, &block)
|
16
|
+
define_method(name.to_s, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
alias :value :element
|
21
|
+
alias :action :element
|
22
|
+
alias :trait :element
|
23
|
+
end
|
24
|
+
|
25
|
+
# custom methods
|
26
|
+
def go_back
|
27
|
+
sleep(1.5)
|
28
|
+
press_back_button
|
29
|
+
sleep(1)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'standard/DroidCommon.rb'
|
2
|
+
# all screens your application screens should be like this. Inheritance from DroidCommon is essential!
|
3
|
+
|
4
|
+
class Test < DroidCommon
|
5
|
+
def initialize(driver)
|
6
|
+
|
7
|
+
@driver = driver
|
8
|
+
|
9
|
+
##### elements on the screen #######
|
10
|
+
|
11
|
+
# elements locators and their x-platform nickname should be like that
|
12
|
+
|
13
|
+
@trait = "* id:'feed_rv'"
|
14
|
+
|
15
|
+
@auth_field = "* id:'auth_fld'"
|
16
|
+
|
17
|
+
@main_ok_button = "* id:'feed_vote_tutorial_go_btn'"
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
# all elements above should have getter for mention them from step definitions
|
22
|
+
attr_reader *Test.new(self).instance_variables.map {|s| s[1..-1]}
|
23
|
+
|
24
|
+
# another way to describe elements
|
25
|
+
|
26
|
+
def tape
|
27
|
+
"* id:'feed_rv'"
|
28
|
+
end
|
29
|
+
|
30
|
+
#### methods ###########
|
31
|
+
|
32
|
+
def authorize(data)
|
33
|
+
tap_on(@auth_field)
|
34
|
+
wait_for_keyboard
|
35
|
+
enter_text(data)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test
|
39
|
+
tap_on(@main_ok_button)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'calabash-android/operations'
|
2
|
+
require 'calabash-android/management/app_installation'
|
3
|
+
require 'calabash-android/cucumber'
|
4
|
+
require 'cucumber'
|
5
|
+
require 'json'
|
6
|
+
require_relative '../../../features/net/screentest_api'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
Before do |scenario|
|
10
|
+
|
11
|
+
ENV['SCREENSHOT_PATH'] = './reports/'
|
12
|
+
|
13
|
+
@scenario_name = scenario.name
|
14
|
+
|
15
|
+
@start_record = true
|
16
|
+
@start_log = true
|
17
|
+
|
18
|
+
scenario_tags = scenario.source_tag_names
|
19
|
+
|
20
|
+
reinstall_apps if scenario_tags.include?('@reinstall')
|
21
|
+
|
22
|
+
clear_app_data if scenario_tags.include?('@clear')
|
23
|
+
|
24
|
+
skip_this_scenario('Сценарий только для iOS') if scenario_tags.include?('@skip')
|
25
|
+
|
26
|
+
if scenario_tags.include?('@screentest')
|
27
|
+
clear_file_with_stack_trace
|
28
|
+
create_feature(@scenario_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
@start_record = true if scenario_tags.include?('@record')
|
32
|
+
|
33
|
+
start_test_server_in_background
|
34
|
+
|
35
|
+
@video_capture = nil
|
36
|
+
|
37
|
+
# start video record
|
38
|
+
if @start_record
|
39
|
+
@video_capture = AndroidVideoCapture.new
|
40
|
+
@video_capture.start_capture
|
41
|
+
@need_convert = false
|
42
|
+
# set video quality: low, medium, high
|
43
|
+
@video_capture.quality = "low"
|
44
|
+
end
|
45
|
+
|
46
|
+
@write_log = nil
|
47
|
+
|
48
|
+
# start write logs
|
49
|
+
if @start_log
|
50
|
+
@write_log = AndroidLogs.new
|
51
|
+
@write_log.start_log
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def file_name(ext)
|
56
|
+
"android_#{Time.now.strftime('%d_%m-%H:%M:%S')}.#{ext}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_folder
|
60
|
+
model = %x(adb devices -l | awk 'NR==2{print $5}')
|
61
|
+
model.slice! "model:"
|
62
|
+
|
63
|
+
@path = "#{ENV['SCREENSHOT_PATH']}#{@scenario_name}_#{model}_#{Time.now.strftime('%d_%m-%H:%M:%S')}/"
|
64
|
+
# Dir.mkdir(@path) unless File.directory?(@path)
|
65
|
+
FileUtils.mkdir_p @path
|
66
|
+
end
|
67
|
+
|
68
|
+
def convert
|
69
|
+
convert_file = "video_#{file_name('mp4')}"
|
70
|
+
@video_capture.convert_video(@video_capture.video_file, convert_file)
|
71
|
+
delete_file(@video_capture.video_file)
|
72
|
+
@video_capture.video_file = convert_file
|
73
|
+
end
|
74
|
+
|
75
|
+
def embed_video
|
76
|
+
unless @video_capture.nil?
|
77
|
+
@video_capture.acquire_capture
|
78
|
+
if File.exist?(@video_capture.video_file)
|
79
|
+
convert if @need_convert
|
80
|
+
embed(@video_capture.video_file, 'video/mp4', "video #{@video_capture.video_file}")
|
81
|
+
FileUtils.mv(@video_capture.video_file, @path)
|
82
|
+
@video_capture.video_file = @path + @video_capture.video_file
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def delete_file(file_name)
|
88
|
+
if File.exist?(file_name)
|
89
|
+
File.delete(file_name)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def embed_logs
|
94
|
+
unless @write_log.nil?
|
95
|
+
if File.exist?(@write_log.log_file)
|
96
|
+
embed(@write_log.log_file, 'log/txt', "log #{@write_log.log_file}")
|
97
|
+
FileUtils.mv(@write_log.log_file, @path)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
After do |scenario|
|
103
|
+
|
104
|
+
@video_capture.stop_capture unless @video_capture.nil?
|
105
|
+
|
106
|
+
@write_log.stop_log unless @write_log.nil?
|
107
|
+
|
108
|
+
scenario_tags = scenario.source_tag_names
|
109
|
+
|
110
|
+
if scenario_tags.include?('@record') && scenario.passed?
|
111
|
+
create_folder
|
112
|
+
embed_video
|
113
|
+
elsif scenario.passed?
|
114
|
+
@video_capture.dispose_capture unless @video_capture.nil?
|
115
|
+
delete_file(@write_log.log_file) unless @write_log.nil?
|
116
|
+
delete_file(@video_capture.video_file) unless @video_capture.nil?
|
117
|
+
end
|
118
|
+
|
119
|
+
if scenario.failed?
|
120
|
+
|
121
|
+
create_folder
|
122
|
+
|
123
|
+
mark_feature_as_not_finished if scenario.source_tag_names.include?('@screentest')
|
124
|
+
|
125
|
+
pretty = JSON.pretty_generate(query("*"))
|
126
|
+
parsed = JSON.parse(pretty)
|
127
|
+
|
128
|
+
for i in 0..query("*").count-1
|
129
|
+
id = parsed[i]['id'].to_s
|
130
|
+
text = parsed[i]['text'].to_s
|
131
|
+
if id != ''
|
132
|
+
File.open("#{@path}id_#{file_name('txt')}", 'a', crlf_newline: true) { |f| f.puts(id.encode(crlf_newline: true))}
|
133
|
+
end
|
134
|
+
if text != ''
|
135
|
+
File.open("#{@path}text_#{file_name('txt')}", 'a', crlf_newline: true) { |f| f.puts(text.encode(crlf_newline: true))}
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
screenshot(prefix: @path, name: "#{file_name('png')}")
|
140
|
+
embed_video
|
141
|
+
embed_logs
|
142
|
+
end
|
143
|
+
|
144
|
+
send_video(@video_capture.video_file) if scenario.source_tag_names.include?('@record')
|
145
|
+
shutdown_test_server
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'timeout'
|
3
|
+
require 'process'
|
4
|
+
require 'calabash-android/operations'
|
5
|
+
require 'calabash-android/env'
|
6
|
+
|
7
|
+
def adb_command
|
8
|
+
"\"#{Calabash::Android::Dependencies.adb_path}\""
|
9
|
+
end
|
10
|
+
|
11
|
+
class AndroidLogs
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@log_file = "#{ENV['SCREENSHOT_PATH']}log_#{Time.now.strftime('%d_%m-%H:%M:%S')}.txt"
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :log_file
|
18
|
+
|
19
|
+
def start_log
|
20
|
+
package = package_name('L.apk')
|
21
|
+
pid_app = %x{adb shell ps | grep #{package} | tr -s [:space:] ' ' | cut -d' ' -f2}
|
22
|
+
@logcat = Open3.popen2e("adb logcat | grep #{pid_app}")
|
23
|
+
@pid = @logcat[2].pid
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop_log
|
27
|
+
%x{ps | grep logcat | grep -v grep | cut -d' ' -f1 | awk '{print $1}' | xargs kill -2}
|
28
|
+
|
29
|
+
begin
|
30
|
+
Timeout.timeout(30) { File.open(@log_file, 'w') { |f| f << @logcat[1].readlines.join("\n") } }
|
31
|
+
rescue Timeout::Error
|
32
|
+
Kernel.puts("Error write log file")
|
33
|
+
@logcat[0].close
|
34
|
+
@logcat[1].close
|
35
|
+
end
|
36
|
+
|
37
|
+
@logcat[0].close
|
38
|
+
@logcat[1].close
|
39
|
+
end
|
40
|
+
end
|