git-contest 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +15 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +24 -0
- data/README.md +217 -0
- data/Rakefile +4 -0
- data/bin/git-contest +43 -0
- data/bin/git-contest-finish +163 -0
- data/bin/git-contest-init +77 -0
- data/bin/git-contest-rebase +76 -0
- data/bin/git-contest-start +68 -0
- data/bin/git-contest-submit +188 -0
- data/git-contest.gemspec +34 -0
- data/lib/contest/driver.rb +15 -0
- data/lib/contest/driver/aizu_online_judge.rb +159 -0
- data/lib/contest/driver/base.rb +103 -0
- data/lib/contest/driver/codeforces.rb +196 -0
- data/lib/contest/driver/common.rb +72 -0
- data/lib/contest/driver/driver_event.rb +30 -0
- data/lib/contest/driver/uva_online_judge.rb +131 -0
- data/lib/git/contest.rb +14 -0
- data/lib/git/contest/common.rb +48 -0
- data/lib/git/contest/git.rb +189 -0
- data/lib/git/contest/test.rb +10 -0
- data/lib/git/contest/version.rb +12 -0
- data/spec/bin/t004_git_contest_submit_spec.rb +143 -0
- data/spec/bin/t005_git_contest_branching_spec.rb +83 -0
- data/spec/bin/t007_git_contest_start_spec.rb +121 -0
- data/spec/bin/t008_git_contest_finish_spec.rb +229 -0
- data/spec/bin/t009_git_contest_init_spec.rb +82 -0
- data/spec/lib/contest/driver/t001_aizu_online_judge_spec.rb +177 -0
- data/spec/lib/contest/driver/t002_codeforces_spec.rb +34 -0
- data/spec/lib/contest/driver/t003_uva_online_judge_spec.rb +33 -0
- data/spec/mock/default_config/config.yml +0 -0
- data/spec/mock/default_config/plugins/driver_dummy.rb +113 -0
- data/spec/mock/t001/002.status_log.xml +55 -0
- data/spec/mock/t001/config.yml +5 -0
- data/spec/mock/t001/description.html +48 -0
- data/spec/mock/t001/status.html +49 -0
- data/spec/mock/t001/status_log.xml +29 -0
- data/spec/mock/t002/my_submissions.html +58 -0
- data/spec/mock/t003/after_submit.html +28 -0
- data/spec/mock/t003/my_submissions.compile_error.html +160 -0
- data/spec/mock/t003/my_submissions.sent_to_judge.html +358 -0
- data/spec/mock/t004/config.yml +17 -0
- data/spec/mock/t005/001/config.yml +5 -0
- data/spec/mock/t006/001/001/001/config.yml +8 -0
- data/spec/mock/t006/001/001/002/config.yml +8 -0
- data/spec/mock/t006/001/001/003/config.yml +8 -0
- data/spec/mock/t006/001/002/001/config.yml +8 -0
- data/spec/mock/t006/001/002/002/config.yml +8 -0
- data/spec/mock/t006/001/002/003/config.yml +8 -0
- data/spec/mock/t006/001/003/001/config.yml +9 -0
- data/spec/mock/t006/001/003/002/config.yml +9 -0
- data/spec/mock/t006/001/003/003/config.yml +9 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/spec_list.txt +1 -0
- data/spec/t006_config_spec.rb +168 -0
- metadata +269 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
# Don't forget --defaults option
|
4
|
+
|
5
|
+
describe "T009: git-contest-init" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
init_env
|
9
|
+
@test_dir = "#{ENV['GIT_CONTEST_TEMP_DIR']}/t009"
|
10
|
+
Dir.mkdir @test_dir
|
11
|
+
Dir.chdir @test_dir
|
12
|
+
# debug_on
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
Dir.chdir '..'
|
17
|
+
Dir.rmdir @test_dir
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "001: --force" do
|
21
|
+
before do
|
22
|
+
Dir.mkdir "001"
|
23
|
+
Dir.chdir "001"
|
24
|
+
end
|
25
|
+
|
26
|
+
after do
|
27
|
+
FileUtils.remove_dir ".git", :force => true
|
28
|
+
Dir.chdir ".."
|
29
|
+
Dir.rmdir "001"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "001: init -> init" do
|
33
|
+
ret1 = bin_exec "init --defaults"
|
34
|
+
ret_config1 = git_do("config --get git.contest.branch.master")
|
35
|
+
ret2 = bin_exec "init --defaults"
|
36
|
+
|
37
|
+
ret_config1.should === "master"
|
38
|
+
ret1.include?("Error: unknown argument").should === false
|
39
|
+
ret2.include?("Error: unknown argument").should === false
|
40
|
+
ret1.include?("Already initialized for git-contest.").should === false
|
41
|
+
ret1.include?("use: git contest init -f").should === false
|
42
|
+
ret2.include?("Already initialized for git-contest.").should === true
|
43
|
+
ret2.include?("use: git contest init -f").should === true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "002: init -> init -f -> init --force" do
|
47
|
+
ret1 = bin_exec "init --defaults"
|
48
|
+
ret_config1 = git_do("config --get git.contest.branch.master")
|
49
|
+
ret2 = bin_exec "init --defaults -f"
|
50
|
+
ret3 = bin_exec "init --defaults --force"
|
51
|
+
ret_config1.should === "master"
|
52
|
+
ret1.include?("Error: unknown argument").should === false
|
53
|
+
ret2.include?("Error: unknown argument").should === false
|
54
|
+
ret3.include?("Error: unknown argument").should === false
|
55
|
+
ret1.include?("Already initialized for git-contest.").should === false
|
56
|
+
ret1.include?("use: git contest init -f").should === false
|
57
|
+
ret2.include?("Already initialized for git-contest.").should === false
|
58
|
+
ret2.include?("use: git contest init -f").should === false
|
59
|
+
ret3.include?("Already initialized for git-contest.").should === false
|
60
|
+
ret3.include?("use: git contest init -f").should === false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "003: init -f -> init -f -> init --force" do
|
64
|
+
ret1 = bin_exec "init --defaults -f"
|
65
|
+
ret_config1 = git_do("config --get git.contest.branch.master")
|
66
|
+
ret2 = bin_exec "init --defaults -f"
|
67
|
+
ret3 = bin_exec "init --defaults --force"
|
68
|
+
ret_config1.should === "master"
|
69
|
+
ret1.include?("Error: unknown argument").should === false
|
70
|
+
ret2.include?("Error: unknown argument").should === false
|
71
|
+
ret3.include?("Error: unknown argument").should === false
|
72
|
+
ret1.include?("Already initialized for git-contest.").should === false
|
73
|
+
ret1.include?("use: git contest init -f").should === false
|
74
|
+
ret2.include?("Already initialized for git-contest.").should === false
|
75
|
+
ret2.include?("use: git contest init -f").should === false
|
76
|
+
ret3.include?("Already initialized for git-contest.").should === false
|
77
|
+
ret3.include?("use: git contest init -f").should === false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'mechanize'
|
4
|
+
require 'contest/driver/aizu_online_judge'
|
5
|
+
|
6
|
+
describe "T001: Contest::Driver::AizuOnlineJudge" do
|
7
|
+
before do
|
8
|
+
# setup driver
|
9
|
+
@driver = Contest::Driver::AizuOnlineJudge.new
|
10
|
+
@driver.stub(:sleep).and_return(0)
|
11
|
+
@driver.client = Mechanize.new {|agent|
|
12
|
+
agent.user_agent_alias = 'Windows IE 7'
|
13
|
+
}
|
14
|
+
ENV['GIT_CONTEST_CONFIG'] = get_path('/mock/t001/config.yml')
|
15
|
+
init
|
16
|
+
|
17
|
+
# basic status_log
|
18
|
+
WebMock
|
19
|
+
.stub_request(
|
20
|
+
:get,
|
21
|
+
/http:\/\/judge\.u-aizu\.ac\.jp\/onlinejudge\/webservice\/status_log/,
|
22
|
+
)
|
23
|
+
.to_return(
|
24
|
+
:status => 200,
|
25
|
+
:body => read_file('/mock/t001/status_log.xml'),
|
26
|
+
:headers => {
|
27
|
+
'Content-Type' => 'text/xml',
|
28
|
+
},
|
29
|
+
)
|
30
|
+
|
31
|
+
# status.jsp: http://judge.u-aizu.ac.jp/onlinejudge/status.jsp
|
32
|
+
WebMock
|
33
|
+
.stub_request(
|
34
|
+
:get,
|
35
|
+
/http:\/\/judge\.u-aizu\.ac\.jp\/onlinejudge\/status/,
|
36
|
+
)
|
37
|
+
.to_return(
|
38
|
+
:status => 200,
|
39
|
+
:body => read_file('/mock/t001/status.html'),
|
40
|
+
:headers => {
|
41
|
+
'Content-Type' => 'text/html',
|
42
|
+
},
|
43
|
+
)
|
44
|
+
|
45
|
+
# description
|
46
|
+
WebMock
|
47
|
+
.stub_request(
|
48
|
+
:get,
|
49
|
+
/http:\/\/judge\.u-aizu\.ac\.jp\/onlinejudge\/description\.jsp\?id=/,
|
50
|
+
)
|
51
|
+
.to_return(
|
52
|
+
:status => 200,
|
53
|
+
:body => read_file('/mock/t001/description.html'),
|
54
|
+
:headers => {
|
55
|
+
'Content-Type' => 'text/html',
|
56
|
+
},
|
57
|
+
)
|
58
|
+
|
59
|
+
# servlet/Submit
|
60
|
+
WebMock
|
61
|
+
.stub_request(
|
62
|
+
:post,
|
63
|
+
/http:\/\/judge\.u-aizu\.ac\.jp\/onlinejudge\/servlet\/Submit/,
|
64
|
+
)
|
65
|
+
.to_return(
|
66
|
+
:status => 200,
|
67
|
+
:body => '',
|
68
|
+
:headers => {
|
69
|
+
'Content-Type' => 'text/html',
|
70
|
+
},
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "001: #get_status_wait" do
|
75
|
+
it "001: Check Status" do
|
76
|
+
ret = @driver.get_status_wait 'test_user', '111'
|
77
|
+
ret.should === "Wrong Answer"
|
78
|
+
end
|
79
|
+
it "002: Check Timeout" do
|
80
|
+
@flag = false
|
81
|
+
proc = Proc.new do
|
82
|
+
@flag = true
|
83
|
+
end
|
84
|
+
@driver.on 'timeout', proc
|
85
|
+
@driver.get_status_wait 'test_user', '999'
|
86
|
+
@driver.off 'timeout', proc
|
87
|
+
@flag.should === true
|
88
|
+
end
|
89
|
+
it "002: Check Timeout noset" do
|
90
|
+
@flag = false
|
91
|
+
proc = Proc.new do
|
92
|
+
@flag = true
|
93
|
+
end
|
94
|
+
@driver.on 'timeout', proc
|
95
|
+
@driver.off 'timeout', proc
|
96
|
+
@driver.get_status_wait 'test_user', '999'
|
97
|
+
@flag.should === false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "002: #get_status_wait" do
|
102
|
+
before do
|
103
|
+
# has 2 statuses
|
104
|
+
WebMock.stub_request(
|
105
|
+
:get,
|
106
|
+
/http:\/\/judge\.u-aizu\.ac\.jp\/onlinejudge\/webservice\/status_log\??.*/
|
107
|
+
).to_return(
|
108
|
+
:status => 200,
|
109
|
+
:body => read_file('/mock/t001/002.status_log.xml'),
|
110
|
+
:headers => {
|
111
|
+
'Content-Type' => 'text/xml',
|
112
|
+
},
|
113
|
+
)
|
114
|
+
end
|
115
|
+
it "001: Check Status" do
|
116
|
+
ret = @driver.get_status_wait 'test_user', '111'
|
117
|
+
ret.should === "Wrong Answer"
|
118
|
+
ret = @driver.get_status_wait 'test_user', '112'
|
119
|
+
ret.should === "Accepted"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "003: #submit" do
|
124
|
+
it "001: Check Event" do
|
125
|
+
FileUtils.touch '/tmp/main.rb'
|
126
|
+
|
127
|
+
@flag_start = false
|
128
|
+
@flag_before_submit = false
|
129
|
+
@flag_after_submit = false
|
130
|
+
@flag_before_wait = false
|
131
|
+
@flag_after_wait = false
|
132
|
+
@flag_finish = false
|
133
|
+
|
134
|
+
proc_start = Proc.new do
|
135
|
+
@flag_start = true
|
136
|
+
end
|
137
|
+
proc_before_submit = Proc.new do |info|
|
138
|
+
@flag_before_submit = true
|
139
|
+
end
|
140
|
+
proc_after_submit = Proc.new do
|
141
|
+
@flag_after_submit = true
|
142
|
+
end
|
143
|
+
proc_before_wait = Proc.new do
|
144
|
+
@flag_before_wait = true
|
145
|
+
end
|
146
|
+
proc_after_wait = Proc.new do
|
147
|
+
@flag_after_wait = true
|
148
|
+
end
|
149
|
+
proc_finish = Proc.new do
|
150
|
+
@flag_finish = true
|
151
|
+
end
|
152
|
+
|
153
|
+
@driver.on 'start', proc_start
|
154
|
+
@driver.on 'before_submit', proc_before_submit
|
155
|
+
@driver.on 'after_submit', proc_after_submit
|
156
|
+
@driver.on 'before_wait', proc_before_wait
|
157
|
+
@driver.on 'after_wait', proc_after_wait
|
158
|
+
@driver.on 'finish', proc_finish
|
159
|
+
|
160
|
+
@driver.submit(
|
161
|
+
{
|
162
|
+
"user" => "test_user",
|
163
|
+
"password" => "password",
|
164
|
+
},
|
165
|
+
'/tmp/main.rb',
|
166
|
+
{
|
167
|
+
:contest_id => '11111',
|
168
|
+
:problem_id => '22222',
|
169
|
+
},
|
170
|
+
)
|
171
|
+
|
172
|
+
@flag = @flag_start && @flag_before_submit && @flag_after_submit && @flag_before_wait && @flag_after_wait && @flag_finish
|
173
|
+
@flag.should === true
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'contest/driver/codeforces'
|
4
|
+
require 'mechanize'
|
5
|
+
|
6
|
+
describe "T002: Contest::Driver::Codeforces" do
|
7
|
+
before do
|
8
|
+
@driver = Contest::Driver::Codeforces.new
|
9
|
+
@driver.stub(:sleep).and_return(0)
|
10
|
+
@driver.client = Mechanize.new {|agent|
|
11
|
+
agent.user_agent_alias = 'Windows IE 7'
|
12
|
+
}
|
13
|
+
|
14
|
+
# basic status_log
|
15
|
+
WebMock.stub_request(
|
16
|
+
:get,
|
17
|
+
/http:\/\/codeforces.com\/contest\/[0-9A-Z]*\/my/
|
18
|
+
).to_return(
|
19
|
+
:status => 200,
|
20
|
+
:body => read_file('/mock/t002/my_submissions.html'),
|
21
|
+
:header => {
|
22
|
+
'Content-Type' => 'text/html',
|
23
|
+
},
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '001: #get_status_wait' do
|
28
|
+
it '001: Check Status' do
|
29
|
+
ret = @driver.get_status_wait 11111, 22222
|
30
|
+
ret.should === "Accepted"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'contest/driver/codeforces'
|
4
|
+
require 'mechanize'
|
5
|
+
|
6
|
+
describe "T003: Contest::Driver::UvaOnlineJudge" do
|
7
|
+
before do
|
8
|
+
@driver = Contest::Driver::UvaOnlineJudge.new
|
9
|
+
@driver.stub(:sleep).and_return(0)
|
10
|
+
@driver.client = Mechanize.new {|agent|
|
11
|
+
agent.user_agent_alias = 'Windows IE 7'
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '001: #get_submission_id' do
|
16
|
+
it '001' do
|
17
|
+
ret = @driver.get_submission_id(read_file('/mock/t003/after_submit.html'))
|
18
|
+
ret.should eq '99999'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '002: #get_submission_status' do
|
23
|
+
it '001: Sent to Judge' do
|
24
|
+
ret = @driver.get_submission_status('99999', read_file('/mock/t003/my_submissions.sent_to_judge.html'))
|
25
|
+
ret.should eq 'Sent to judge'
|
26
|
+
end
|
27
|
+
it '002: Compile Error' do
|
28
|
+
ret = @driver.get_submission_status('99999', read_file('/mock/t003/my_submissions.compile_error.html'))
|
29
|
+
ret.should eq 'Compilation error'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
File without changes
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'contest/driver/common'
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
module Contest
|
5
|
+
module Driver
|
6
|
+
class Dummy < DriverBase
|
7
|
+
def get_opts_ext
|
8
|
+
define_options do
|
9
|
+
opt(
|
10
|
+
:problem_id,
|
11
|
+
"Problem ID (Ex: 1000, 123, 0123, etc...)",
|
12
|
+
:type => :string,
|
13
|
+
:required => true,
|
14
|
+
)
|
15
|
+
opt(
|
16
|
+
:contest_id,
|
17
|
+
"Contest ID (Ex: 1000, 123, 0123, etc...)",
|
18
|
+
:type => :string,
|
19
|
+
:required => true,
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_site_name
|
25
|
+
"Dummy"
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_problem_id(options)
|
29
|
+
"#{options[:contest_id]}#{options[:problem_id]}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_desc
|
33
|
+
"This is Dummy"
|
34
|
+
end
|
35
|
+
|
36
|
+
def resolve_language(label)
|
37
|
+
case label
|
38
|
+
when "clang"
|
39
|
+
return "C"
|
40
|
+
when "cpp"
|
41
|
+
return "C++"
|
42
|
+
when "java"
|
43
|
+
return "JAVA"
|
44
|
+
when "cpp11"
|
45
|
+
return "C++11"
|
46
|
+
when "cs"
|
47
|
+
return "C#"
|
48
|
+
when "dlang"
|
49
|
+
return "D"
|
50
|
+
when "golang"
|
51
|
+
return "Go"
|
52
|
+
when "ruby"
|
53
|
+
return "Ruby"
|
54
|
+
when "python2"
|
55
|
+
return "Python2"
|
56
|
+
when "python3"
|
57
|
+
return "Python"
|
58
|
+
when "php"
|
59
|
+
return "PHP"
|
60
|
+
when "javascript"
|
61
|
+
return "JavaScript"
|
62
|
+
else
|
63
|
+
abort "unknown languag"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def submit_ext(config, source_path, options)
|
68
|
+
# start
|
69
|
+
trigger 'start'
|
70
|
+
|
71
|
+
# submit
|
72
|
+
trigger(
|
73
|
+
'before_submit',
|
74
|
+
{
|
75
|
+
:source => source_path
|
76
|
+
},
|
77
|
+
)
|
78
|
+
trigger 'after_submit'
|
79
|
+
|
80
|
+
# need to get the newest waiting submissionId
|
81
|
+
trigger 'before_wait'
|
82
|
+
|
83
|
+
# wait result
|
84
|
+
status = ''
|
85
|
+
File.open source_path, 'r' do |file|
|
86
|
+
line = file.read
|
87
|
+
if line == 'wa-code'
|
88
|
+
status = 'Wrong Answer'
|
89
|
+
elsif line == 'ac-code'
|
90
|
+
status = 'Accepted'
|
91
|
+
elsif line == 'tle-code'
|
92
|
+
status = 'Time Limit Exceeded'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
trigger(
|
96
|
+
'after_wait',
|
97
|
+
{
|
98
|
+
:submission_id => '99999',
|
99
|
+
:status => status,
|
100
|
+
:result => get_commit_message($config["submit_rules"]["message"], status, options),
|
101
|
+
}
|
102
|
+
)
|
103
|
+
trigger 'finish'
|
104
|
+
|
105
|
+
status
|
106
|
+
end
|
107
|
+
|
108
|
+
if ENV['TEST_MODE'] === 'TRUE'
|
109
|
+
attr_writer :client
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<status_list>
|
3
|
+
<status>
|
4
|
+
<run_id>
|
5
|
+
112
|
6
|
+
</run_id>
|
7
|
+
<user_id>
|
8
|
+
test_user
|
9
|
+
</user_id>
|
10
|
+
<problem_id>
|
11
|
+
222
|
12
|
+
</problem_id>
|
13
|
+
<status>
|
14
|
+
Accepted
|
15
|
+
</status>
|
16
|
+
<language>
|
17
|
+
Ruby
|
18
|
+
</language>
|
19
|
+
<cputime>
|
20
|
+
333
|
21
|
+
</cputime>
|
22
|
+
<memory>
|
23
|
+
444
|
24
|
+
</memory>
|
25
|
+
<code_size>
|
26
|
+
555
|
27
|
+
</code_size>
|
28
|
+
</status>
|
29
|
+
<status>
|
30
|
+
<run_id>
|
31
|
+
111
|
32
|
+
</run_id>
|
33
|
+
<user_id>
|
34
|
+
test_user
|
35
|
+
</user_id>
|
36
|
+
<problem_id>
|
37
|
+
222
|
38
|
+
</problem_id>
|
39
|
+
<status>
|
40
|
+
Wrong Answer
|
41
|
+
</status>
|
42
|
+
<language>
|
43
|
+
Ruby
|
44
|
+
</language>
|
45
|
+
<cputime>
|
46
|
+
333
|
47
|
+
</cputime>
|
48
|
+
<memory>
|
49
|
+
444
|
50
|
+
</memory>
|
51
|
+
<code_size>
|
52
|
+
555
|
53
|
+
</code_size>
|
54
|
+
</status>
|
55
|
+
</status_list>
|