Class: AtCoderFriends::TestRunner::Base

Inherits:
Object
  • Object
show all
Includes:
PathUtil
Defined in:
lib/at_coder_friends/test_runner/base.rb

Overview

run tests for the specified program.

Direct Known Subclasses

Judge, Sample

Constant Summary collapse

STATUS_STR =
{
  OK: '<< OK >>'.green,
  WA: '!!!!! WA !!!!!'.red,
  RE: '!!!!! RE !!!!!'.red,
  NO_EXP: ''
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from PathUtil

#makedirs_unless

Constructor Details

#initialize(ctx) ⇒ Base

Returns a new instance of Base.



21
22
23
24
25
# File 'lib/at_coder_friends/test_runner/base.rb', line 21

def initialize(ctx)
  @ctx = ctx
  @path, @dir, @prg, @base, @ext, @q = ctx.path_info.components
  @detail = true
end

Instance Attribute Details

#baseObject (readonly)

Returns the value of attribute base.



19
20
21
# File 'lib/at_coder_friends/test_runner/base.rb', line 19

def base
  @base
end

#ctxObject (readonly)

Returns the value of attribute ctx.



19
20
21
# File 'lib/at_coder_friends/test_runner/base.rb', line 19

def ctx
  @ctx
end

#dirObject (readonly)

Returns the value of attribute dir.



19
20
21
# File 'lib/at_coder_friends/test_runner/base.rb', line 19

def dir
  @dir
end

#extObject (readonly)

Returns the value of attribute ext.



19
20
21
# File 'lib/at_coder_friends/test_runner/base.rb', line 19

def ext
  @ext
end

#pathObject (readonly)

Returns the value of attribute path.



19
20
21
# File 'lib/at_coder_friends/test_runner/base.rb', line 19

def path
  @path
end

#prgObject (readonly)

Returns the value of attribute prg.



19
20
21
# File 'lib/at_coder_friends/test_runner/base.rb', line 19

def prg
  @prg
end

#qObject (readonly)

Returns the value of attribute q.



19
20
21
# File 'lib/at_coder_friends/test_runner/base.rb', line 19

def q
  @q
end

Instance Method Details

#call_remote_test(infile) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/at_coder_friends/test_runner/base.rb', line 88

def call_remote_test(infile)
  res = ctx.scraping_agent.code_test(infile)
  (res && res['Result']) || (return [false, 'Remote test failed.'])

  puts "Exit code: #{res.dig('Result', 'ExitCode')}"
  puts "Time: #{res.dig('Result', 'TimeConsumption')}ms"
  puts "Memory: #{res.dig('Result', 'MemoryConsumption')}KB"

  res.dig('Result', 'ExitCode').zero? || (return [false, res['Stderr']])
  [true, res['Stdout']]
end

#check_file(infile, outfile) ⇒ Object



69
70
71
72
73
74
75
76
# File 'lib/at_coder_friends/test_runner/base.rb', line 69

def check_file(infile, outfile)
  unless File.exist?(infile)
    puts "#{File.basename(infile)} not found."
    return false
  end
  makedirs_unless(File.dirname(outfile))
  true
end

#check_status(is_success, result, expected) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/at_coder_friends/test_runner/base.rb', line 100

def check_status(is_success, result, expected)
  if !is_success
    :RE
  elsif !expected
    :NO_EXP
  elsif result != expected
    :WA
  else
    :OK
  end
end

#detail_str(input, result, expected) ⇒ Object



112
113
114
115
116
117
118
119
120
121
# File 'lib/at_coder_friends/test_runner/base.rb', line 112

def detail_str(input, result, expected)
  ret = ''
  ret += "-- input --\n"
  ret += input
  ret += "-- expected --\n"
  ret += expected || "(no expected value)\n"
  ret += "-- result --\n"
  ret += result
  ret
end

#local_test(infile, outfile) ⇒ Object



78
79
80
# File 'lib/at_coder_friends/test_runner/base.rb', line 78

def local_test(infile, outfile)
  system("#{test_cmd} < \"#{infile}\" > \"#{outfile}\"")
end

#remote_test(infile, outfile) ⇒ Object



82
83
84
85
86
# File 'lib/at_coder_friends/test_runner/base.rb', line 82

def remote_test(infile, outfile)
  is_success, result = call_remote_test(infile)
  File.write(outfile, result)
  is_success
end

#run_test(id, infile, outfile, expfile) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/at_coder_friends/test_runner/base.rb', line 55

def run_test(id, infile, outfile, expfile)
  puts "==== #{id} ===="
  return false unless check_file(infile, outfile)

  is_success = send(test_mtd, infile, outfile)
  input = File.read(infile)
  result = File.read(outfile)
  expected = File.exist?(expfile) && File.read(expfile)
  status = check_status(is_success, result, expected)
  print detail_str(input, result, expected) if @detail
  puts STATUS_STR[status]
  status == :OK
end

#test_cmdObject



27
28
29
30
31
32
33
# File 'lib/at_coder_friends/test_runner/base.rb', line 27

def test_cmd
  @test_cmd ||= begin
    cmds = ctx.config.dig('ext_settings', ext, 'test_cmd')
    cmd = cmds && (cmds[which_os.to_s] || cmds['default'])
    cmd&.gsub('{dir}', dir)&.gsub('{base}', base)
  end
end

#test_locObject



35
36
37
38
39
40
41
42
43
# File 'lib/at_coder_friends/test_runner/base.rb', line 35

def test_loc
  if test_cmd
    'local'
  elsif ctx.scraping_agent.respond_to?(:code_test)
    'remote'
  else
    raise AppError, "test_cmd for .#{ext} is not specified."
  end
end

#test_mtdObject



45
46
47
48
49
50
51
52
53
# File 'lib/at_coder_friends/test_runner/base.rb', line 45

def test_mtd
  if test_cmd
    :local_test
  elsif ctx.scraping_agent.respond_to?(:code_test)
    :remote_test
  else
    raise AppError, "test_cmd for .#{ext} is not specified."
  end
end

#which_osObject



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/at_coder_friends/test_runner/base.rb', line 123

def which_os
  @which_os ||=
    case RbConfig::CONFIG['host_os']
    when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
      :windows
    when /darwin|mac os/
      :macosx
    when /linux/
      :linux
    when /solaris|bsd/
      :unix
    else
      :unknown
    end
end