Skip to content

Commit

Permalink
Merge pull request #398 from blackm00n/use.export.summary.for.source.…
Browse files Browse the repository at this point in the history
…files.detection

Use `llvm-cov export` to detect source files per binary
  • Loading branch information
ksuther authored Jul 10, 2018
2 parents 69b7411 + 2d05457 commit ad8415d
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 9 deletions.
42 changes: 34 additions & 8 deletions lib/slather/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,26 @@ def gcov_coverage_files

def profdata_coverage_files
coverage_files = []
source_files = find_source_files || []
line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0')

if self.binary_file
self.binary_file.each do |binary_path|
files = profdata_llvm_cov_output(binary_path, source_files).split("\n\n")
coverage_json_string = llvm_cov_export_output(binary_path)
coverage_json = JSON.parse(coverage_json_string)
pathnames_per_binary = coverage_json["data"].reduce([]) do |result, chunk|
result.concat(chunk["files"].map do |file|
Pathname(file["filename"]).realpath
end)
end

files = profdata_llvm_cov_output(binary_path, pathnames_per_binary).split("\n\n")

coverage_files.concat(files.map do |source|
coverage_file = coverage_file_class.new(self, source, line_numbers_first)
# If a single source file is used, the resulting output does not contain the file name.
coverage_file.source_file_pathname = source_files.first if source_files.count == 1
coverage_file.source_file_pathname = pathnames_per_binary.first if pathnames_per_binary.count == 1
!coverage_file.ignored? ? coverage_file : nil
end.compact)

if !source_files.empty?
coverage_file_paths = coverage_files.map { |file| file.source_file_pathname }.to_set
source_files.select! { |path| !coverage_file_paths.include?(path) }
end
end
end

Expand Down Expand Up @@ -201,6 +203,30 @@ def profdata_file
end
private :profdata_file

def unsafe_llvm_cov_export_output(binary_path)
profdata_file_arg = profdata_file
if profdata_file_arg == nil
raise StandardError, "No Coverage.profdata files found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
end

if binary_path == nil
raise StandardError, "No binary file found."
end

llvm_cov_args = %W(export -instr-profile #{profdata_file_arg} #{binary_path})
if self.arch
llvm_cov_args << "--arch" << self.arch
end
`xcrun llvm-cov #{llvm_cov_args.shelljoin}`
end
private :unsafe_llvm_cov_export_output

def llvm_cov_export_output(binary_path)
output = unsafe_llvm_cov_export_output(binary_path)
output.valid_encoding? ? output : output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace)
end
private :llvm_cov_export_output

def unsafe_profdata_llvm_cov_output(binary_path, source_files)
profdata_file_arg = profdata_file
if profdata_file_arg == nil
Expand Down
9 changes: 9 additions & 0 deletions spec/slather/coverage_service/coveralls_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@
before(:each) {
fixtures_project.ci_service = :travis_ci
project_root = Pathname("./").realpath
allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(%q(
{
"data":[
{
"files":[]
}
]
}
))
allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return("#{project_root}/spec/fixtures/fixtures/fixtures.m:
| 1|//
| 2|// fixtures.m
Expand Down
10 changes: 9 additions & 1 deletion spec/slather/coverage_service/hardcover_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@
allow(Slather::Project).to receive(:yml).and_return(fixture_yaml)
fixtures_project.ci_service = :jenkins_ci
project_root = Pathname("./").realpath
allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(%q(
{
"data":[
{
"files":[]
}
]
}
))
allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return("#{project_root}/spec/fixtures/fixtures/fixtures.m:
| 1|//
| 2|// fixtures.m
Expand Down Expand Up @@ -104,7 +113,6 @@

it "should always remove the hardcover_json_file after it's done" do
allow(fixtures_project).to receive(:`)

allow(fixtures_project).to receive(:jenkins_job_id).and_return("slather-master/9182")
allow(fixtures_project).to receive(:coverage_service_url).and_return("http://api.hardcover.io")
fixtures_project.post
Expand Down
41 changes: 41 additions & 0 deletions spec/slather/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile
allow(Dir).to receive(:[]).and_call_original
allow(Dir).to receive(:[]).with("#{fixtures_project.build_directory}/**/Coverage.profdata").and_return(["/some/path/Coverage.profdata"])
allow(fixtures_project).to receive(:binary_file).and_return(["Fixtures"])
allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(%q(
{
"data":[
{
"files":[
{
"filename":"spec/fixtures/fixtures/Fixtures.swift"
}
]
}
]
}
))
allow(fixtures_project).to receive(:profdata_llvm_cov_output).and_return("#{FIXTURES_SWIFT_FILE_PATH}:
| 0|
| 1|import UIKit
Expand Down Expand Up @@ -111,6 +124,18 @@ class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile
allow(fixtures_project).to receive(:ignore_list).and_return([])
allow(Dir).to receive(:[]).with("#{fixtures_project.build_directory}/**/Coverage.profdata").and_return(["/some/path/Coverage.profdata"])
allow(fixtures_project).to receive(:binary_file).and_return(["Fixtures"])
allow(fixtures_project).to receive(:unsafe_llvm_cov_export_output).and_return("
{
\"data\":[
{
\"files\":[
{
\"filename\":\"sp\145c/fixtures/fixtures/fixtures.m\"
}
]
}
]
}")
allow(fixtures_project).to receive(:unsafe_profdata_llvm_cov_output).and_return("#{FIXTURES_SWIFT_FILE_PATH}:
1| 8| func application(application: \255, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
1| 9| return true
Expand Down Expand Up @@ -563,6 +588,22 @@ class SpecXcode7CoverageFile < Slather::ProfdataCoverageFile
end

it "should print out the coverage for each file, and then total coverage" do
allow(fixtures_project).to receive(:llvm_cov_export_output).and_return(%q(
{
"data":[
{
"files":[
{
"filename":"spec/fixtures/fixtures/fixtures.m"
},
{
"filename":"spec/fixtures/fixturesTwo/fixturesTwo.m"
}
]
}
]
}
))
["spec/fixtures/fixtures/fixtures.m: 3 of 6 lines (50.00%)",
"spec/fixtures/fixturesTwo/fixturesTwo.m: 6 of 6 lines (100.00%)",
"Tested 9/12 statements",
Expand Down

0 comments on commit ad8415d

Please sign in to comment.