asautotest 0.0.1
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.
- data/LICENSE +674 -0
- data/README.rdoc +182 -0
- data/bin/asautotest +437 -0
- data/bin/flash-policy-server +88 -0
- data/lib/asautotest/compilation-output-parser.rb +115 -0
- data/lib/asautotest/compilation-result.rb +102 -0
- data/lib/asautotest/compilation-runner.rb +135 -0
- data/lib/asautotest/compiler-shell.rb +78 -0
- data/lib/asautotest/logging.rb +124 -0
- data/lib/asautotest/problematic-file.rb +526 -0
- data/lib/asautotest/stopwatch.rb +50 -0
- data/lib/asautotest/test-runner.rb +424 -0
- data/lib/asautotest/utilities.rb +62 -0
- metadata +78 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# flash-policy-server --- simple Flash security policy file server
|
4
|
+
# Copyright (C) 2010 Go Interactive
|
5
|
+
|
6
|
+
# This file is part of ASAutotest.
|
7
|
+
|
8
|
+
# ASAutotest is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
|
13
|
+
# ASAutotest is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with ASAutotest. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
|
21
|
+
require "socket"
|
22
|
+
require "timeout"
|
23
|
+
|
24
|
+
class PolicyServer
|
25
|
+
PORT = 843
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@server = TCPServer.new(PORT)
|
29
|
+
@server.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
30
|
+
|
31
|
+
info "Listening to localhost:#{PORT}."
|
32
|
+
end
|
33
|
+
|
34
|
+
def run
|
35
|
+
loop { accept }
|
36
|
+
end
|
37
|
+
|
38
|
+
def accept
|
39
|
+
handle_socket(@server.accept)
|
40
|
+
end
|
41
|
+
|
42
|
+
def info(message)
|
43
|
+
puts info_string(message)
|
44
|
+
end
|
45
|
+
|
46
|
+
def info_string(message)
|
47
|
+
"policy-server: #{message}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def begin_info(message)
|
51
|
+
STDOUT.print info_string("#{message}...")
|
52
|
+
STDOUT.flush
|
53
|
+
end
|
54
|
+
|
55
|
+
def end_info(message)
|
56
|
+
STDOUT.puts " #{message}."
|
57
|
+
end
|
58
|
+
|
59
|
+
EXPECTED_REQUEST = "<policy-file-request/>\0"
|
60
|
+
|
61
|
+
def handle_socket(socket)
|
62
|
+
source = "#{socket.peeraddr[2]}:#{socket.peeraddr[1]}"
|
63
|
+
begin_info "Serving #{source}"
|
64
|
+
request = Timeout.timeout(3) { socket.read(EXPECTED_REQUEST.size) }
|
65
|
+
if request == EXPECTED_REQUEST
|
66
|
+
socket.print(policy_xml)
|
67
|
+
socket.print("\0")
|
68
|
+
end_info "ok"
|
69
|
+
else
|
70
|
+
end_info "recieved garbage: #{request.inspect}"
|
71
|
+
end
|
72
|
+
rescue Timeout::Error
|
73
|
+
end_info "timeout"
|
74
|
+
ensure
|
75
|
+
socket.close
|
76
|
+
end
|
77
|
+
|
78
|
+
def policy_xml
|
79
|
+
<<-end_xml
|
80
|
+
<cross-domain-policy>
|
81
|
+
<site-control permitted-cross-domain-policies="master-only"/>
|
82
|
+
<allow-access-from domain="*" to-ports="*"/>
|
83
|
+
</cross-domain-policy>
|
84
|
+
end_xml
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
PolicyServer.new.run
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# compilation-output-parser.rb --- parse the output of one compilation
|
3
|
+
# Copyright (C) 2010 Go Interactive
|
4
|
+
|
5
|
+
# This file is part of ASAutotest.
|
6
|
+
|
7
|
+
# ASAutotest is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
|
12
|
+
# ASAutotest is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with ASAutotest. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module ASAutotest
|
21
|
+
class OutputParser
|
22
|
+
def initialize(output, request, stopwatch, result)
|
23
|
+
@output = output
|
24
|
+
@request = request
|
25
|
+
@stopwatch = stopwatch
|
26
|
+
@result = result
|
27
|
+
|
28
|
+
@problematic_file_names = Set.new
|
29
|
+
@n_problems = 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.parse(*arguments)
|
33
|
+
new(*arguments).run
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
parse_lines
|
38
|
+
add_summary
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_lines
|
42
|
+
@result.source_directories = @request.source_directories
|
43
|
+
|
44
|
+
while has_more_lines?
|
45
|
+
line = read_line
|
46
|
+
puts ">> #{line}" if Logging.verbose?
|
47
|
+
parse_line(line)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_line(line)
|
52
|
+
case line
|
53
|
+
when /^Loading configuration file /
|
54
|
+
when /^fcsh: Assigned (\d+) as the compile target id/
|
55
|
+
@request.compile_id = $1
|
56
|
+
when /^Recompile: /
|
57
|
+
when /^Reason: /
|
58
|
+
when /^\s*$/
|
59
|
+
when /\(\d+ bytes\)$/
|
60
|
+
@successful = true
|
61
|
+
when /^Nothing has changed /
|
62
|
+
@n_recompiled_files = 0
|
63
|
+
when /^Files changed: (\d+) Files affected: (\d+)/
|
64
|
+
@n_recompiled_files = $1.to_i + $2.to_i
|
65
|
+
when /^(.*?)\((\d+)\): col: (\d+) (.*)/
|
66
|
+
file_name = $1
|
67
|
+
line_number = $2.to_i
|
68
|
+
column_number = $3.to_i - 1
|
69
|
+
message = $4
|
70
|
+
source_line = read_lines(4)[1]
|
71
|
+
|
72
|
+
location = Location[line_number, column_number, source_line]
|
73
|
+
problem = Problem[message, location]
|
74
|
+
|
75
|
+
add_problem(file_name, problem)
|
76
|
+
when /^Error: (.*)/
|
77
|
+
add_problem(nil, Problem[$1, nil])
|
78
|
+
when /^(.*?): (.*)/
|
79
|
+
add_problem($1, Problem[$2, nil])
|
80
|
+
else
|
81
|
+
@result.add_unrecognized_line(line)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_problem(file_name, problem)
|
86
|
+
@first_problem ||= problem
|
87
|
+
@problematic_file_names << file_name
|
88
|
+
@n_problems += 1
|
89
|
+
@result.add_problem(file_name, problem)
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_summary
|
93
|
+
@result.add_summary \
|
94
|
+
:request => @request,
|
95
|
+
:successful? => @successful,
|
96
|
+
:n_recompiled_files => @n_recompiled_files,
|
97
|
+
:n_problematic_files => @problematic_file_names.size,
|
98
|
+
:n_problems => @n_problems,
|
99
|
+
:first_problem => @first_problem,
|
100
|
+
:compilation_time => @stopwatch
|
101
|
+
end
|
102
|
+
|
103
|
+
def has_more_lines?
|
104
|
+
not @output.empty?
|
105
|
+
end
|
106
|
+
|
107
|
+
def read_lines(n)
|
108
|
+
@output.shift(n).map(&:chomp)
|
109
|
+
end
|
110
|
+
|
111
|
+
def read_line
|
112
|
+
@output.shift.chomp
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# compilation-result.rb --- collect the results of a compilation
|
3
|
+
# Copyright (C) 2010 Go Interactive
|
4
|
+
|
5
|
+
# This file is part of ASAutotest.
|
6
|
+
|
7
|
+
# ASAutotest is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
|
12
|
+
# ASAutotest is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with ASAutotest. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module ASAutotest
|
21
|
+
class CompilationResult
|
22
|
+
attr_reader :n_recompiled_files
|
23
|
+
attr_reader :problematic_files
|
24
|
+
attr_reader :unrecognized_lines
|
25
|
+
attr_reader :summaries
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@problematic_files = {}
|
29
|
+
@n_recompiled_files = nil
|
30
|
+
@unrecognized_lines = []
|
31
|
+
@summaries = []
|
32
|
+
end
|
33
|
+
|
34
|
+
# ----------------------------------------------------
|
35
|
+
|
36
|
+
def source_directories= value
|
37
|
+
@source_directories = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_problem(file_name, problem)
|
41
|
+
get_problematic_file(file_name) << problem unless
|
42
|
+
@typing == :dynamic and problem.type_warning?
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_problematic_file(file_name)
|
46
|
+
if @problematic_files.include? file_name
|
47
|
+
@problematic_files[file_name]
|
48
|
+
else
|
49
|
+
@problematic_files[file_name] =
|
50
|
+
ProblematicFile.new(file_name, @source_directories)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# ----------------------------------------------------
|
55
|
+
|
56
|
+
def add_unrecognized_line(line)
|
57
|
+
@unrecognized_lines << line
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_summary(summary)
|
61
|
+
@summaries << summary
|
62
|
+
end
|
63
|
+
|
64
|
+
# ----------------------------------------------------
|
65
|
+
|
66
|
+
def any_type_warnings?
|
67
|
+
@problematic_files.values.any? &:any_type_warnings?
|
68
|
+
end
|
69
|
+
|
70
|
+
def successful?
|
71
|
+
@summaries.all? { |x| x[:successful?] }
|
72
|
+
end
|
73
|
+
|
74
|
+
def n_problematic_files
|
75
|
+
@problematic_files.values.size
|
76
|
+
end
|
77
|
+
|
78
|
+
def n_problems
|
79
|
+
@problematic_files.values.inject(0) { |a, x| a + x.n_problems }
|
80
|
+
end
|
81
|
+
|
82
|
+
def failed?
|
83
|
+
not successful?
|
84
|
+
end
|
85
|
+
|
86
|
+
def bootstrap?
|
87
|
+
@summaries.all? { |x| x[:n_recompiled_files] == nil }
|
88
|
+
end
|
89
|
+
|
90
|
+
def n_recompiled_files
|
91
|
+
@summaries.inject(0) { |a, x| a + x[:n_recompiled_files] }
|
92
|
+
end
|
93
|
+
|
94
|
+
def recompilation?
|
95
|
+
not bootstrap?
|
96
|
+
end
|
97
|
+
|
98
|
+
def did_anything?
|
99
|
+
bootstrap? or n_recompiled_files > 0
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# compilation-runner.rb --- run compilations and report the results
|
3
|
+
# Copyright (C) 2010 Go Interactive
|
4
|
+
|
5
|
+
# This file is part of ASAutotest.
|
6
|
+
|
7
|
+
# ASAutotest is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
|
12
|
+
# ASAutotest is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with ASAutotest. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require "asautotest/logging"
|
21
|
+
|
22
|
+
module ASAutotest
|
23
|
+
class CompilationRunner
|
24
|
+
class CompilationFailure < Exception ; end
|
25
|
+
|
26
|
+
include Logging
|
27
|
+
|
28
|
+
attr_reader :result
|
29
|
+
|
30
|
+
def initialize(shell, options)
|
31
|
+
@shell = shell
|
32
|
+
@typing = options[:typing]
|
33
|
+
@result = CompilationResult.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
@stopwatch = Stopwatch.new
|
38
|
+
whisper_commands
|
39
|
+
compile
|
40
|
+
@stopwatch.stop
|
41
|
+
print_report
|
42
|
+
end
|
43
|
+
|
44
|
+
def whisper_commands
|
45
|
+
for command in @shell.compilation_commands
|
46
|
+
whisper "$ #{command}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def compile
|
51
|
+
say("Compiling") do |status|
|
52
|
+
@shell.run_compilations(@result)
|
53
|
+
|
54
|
+
if @result.failed?
|
55
|
+
status << "failed"
|
56
|
+
elsif @result.did_anything?
|
57
|
+
files = if @result.bootstrap?
|
58
|
+
"everything"
|
59
|
+
else
|
60
|
+
n_x(@result.n_recompiled_files, "file")
|
61
|
+
end
|
62
|
+
status << "recompiled #{files} in #{compilation_time}"
|
63
|
+
else
|
64
|
+
status << "nothing changed"
|
65
|
+
end
|
66
|
+
|
67
|
+
if @result.successful?
|
68
|
+
for summary in @result.summaries
|
69
|
+
title = File.basename(summary[:request].source_file_name)
|
70
|
+
if summary[:successful?] and summary[:n_recompiled_files] != 0
|
71
|
+
files = if summary[:n_recompiled_files]
|
72
|
+
n_x(summary[:n_recompiled_files], "file")
|
73
|
+
else
|
74
|
+
"everything"
|
75
|
+
end
|
76
|
+
time = "#{summary[:compilation_time].to_s(1)}s"
|
77
|
+
growl_success title, "Compiled #{files} in #{time}."
|
78
|
+
end
|
79
|
+
end
|
80
|
+
else
|
81
|
+
summary = @result.summaries.find { |x| not x[:successful?] }
|
82
|
+
file_name = summary[:first_problem].file.basename
|
83
|
+
line_number = summary[:first_problem].line_number
|
84
|
+
message = summary[:first_problem].plain_message
|
85
|
+
growl_error "#{file_name}, line #{line_number}", message
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def n_x(n, x)
|
91
|
+
"#{n} #{x}#{n == 1 ? "" : "s"}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def growl_success(title, message)
|
95
|
+
if ASAutotest::growl_enabled
|
96
|
+
options = { :title => title, :icon => "as" }
|
97
|
+
if ASAutotest::displaying_growl_error
|
98
|
+
options[:identifier] = GROWL_ERROR_TOKEN
|
99
|
+
ASAutotest::displaying_growl_error = false
|
100
|
+
end
|
101
|
+
Growl.notify(message, options)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def growl_error(title, message)
|
106
|
+
if ASAutotest::growl_enabled
|
107
|
+
Growl.notify_error message,
|
108
|
+
:title => title, :sticky => true,
|
109
|
+
:identifier => GROWL_ERROR_TOKEN
|
110
|
+
ASAutotest::displaying_growl_error = true
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def compilation_time
|
115
|
+
"~#{@stopwatch.to_s(1)} seconds"
|
116
|
+
end
|
117
|
+
|
118
|
+
def print_report
|
119
|
+
for line in @result.unrecognized_lines
|
120
|
+
barf line
|
121
|
+
end
|
122
|
+
|
123
|
+
for name, file in @result.problematic_files
|
124
|
+
file.print_report
|
125
|
+
end
|
126
|
+
|
127
|
+
puts unless @result.problematic_files.empty?
|
128
|
+
|
129
|
+
if @typing == nil and @result.any_type_warnings?
|
130
|
+
hint "Use --dynamic-typing to disable type declaration warnings,"
|
131
|
+
hint "or --static-typing to disable this hint."
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# compiler-shell.rb --- wrapper around the fcsh executable
|
3
|
+
# Copyright (C) 2010 Go Interactive
|
4
|
+
|
5
|
+
# This file is part of ASAutotest.
|
6
|
+
|
7
|
+
# ASAutotest is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
|
12
|
+
# ASAutotest is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with ASAutotest. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module ASAutotest
|
21
|
+
class CompilerShell
|
22
|
+
PROMPT = "\n(fcsh) "
|
23
|
+
|
24
|
+
class PromptNotFound < Exception ; end
|
25
|
+
|
26
|
+
include Logging
|
27
|
+
|
28
|
+
attr_reader :compilation_requests
|
29
|
+
|
30
|
+
def initialize(options)
|
31
|
+
@compilation_requests = options[:compilation_requests]
|
32
|
+
end
|
33
|
+
|
34
|
+
def start
|
35
|
+
say "Starting compiler shell" do
|
36
|
+
@process = IO.popen("#{FCSH} 2>&1", "r+")
|
37
|
+
read_until_prompt
|
38
|
+
end
|
39
|
+
rescue PromptNotFound => error
|
40
|
+
shout "Could not find FCSH prompt:"
|
41
|
+
for line in error.message.lines do
|
42
|
+
barf line.chomp
|
43
|
+
end
|
44
|
+
if error.message.include? "command not found"
|
45
|
+
shout "Please make sure that fcsh is in your PATH."
|
46
|
+
shout "Alternatively, set the ‘FCSH’ environment variable."
|
47
|
+
end
|
48
|
+
exit -1
|
49
|
+
end
|
50
|
+
|
51
|
+
def run_compilations(result)
|
52
|
+
for request in @compilation_requests
|
53
|
+
run_compilation(request, result)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def compilation_commands
|
58
|
+
@compilation_requests.map { |x| x.compilation_command }
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_compilation(request, result)
|
62
|
+
stopwatch = Stopwatch.new
|
63
|
+
@process.puts(request.compilation_command)
|
64
|
+
OutputParser.parse(read_until_prompt, request, stopwatch, result)
|
65
|
+
stopwatch.stop
|
66
|
+
end
|
67
|
+
|
68
|
+
def read_until_prompt
|
69
|
+
result = ""
|
70
|
+
until result.include? PROMPT
|
71
|
+
result << @process.readpartial(100)
|
72
|
+
end
|
73
|
+
result.lines.entries[0 .. -2]
|
74
|
+
rescue EOFError
|
75
|
+
raise PromptNotFound, result
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|