diff --git a/java/jacoco.go b/java/jacoco.go index b26b046d2..c4b3e6edd 100644 --- a/java/jacoco.go +++ b/java/jacoco.go @@ -17,6 +17,7 @@ package java // Rules for instrumenting classes using jacoco import ( + "fmt" "strings" "github.com/google/blueprint" @@ -59,41 +60,51 @@ func jacocoInstrumentJar(ctx android.ModuleContext, outputJar, strippedJar andro }) } -func (j *Module) jacocoStripSpecs(ctx android.ModuleContext) string { - includes := jacocoFiltersToSpecs(ctx, - j.properties.Jacoco.Include_filter, "jacoco.include_filter") - excludes := jacocoFiltersToSpecs(ctx, - j.properties.Jacoco.Exclude_filter, "jacoco.exclude_filter") +func (j *Module) jacocoModuleToZipCommand(ctx android.ModuleContext) string { + includes, err := jacocoFiltersToSpecs(j.properties.Jacoco.Include_filter) + if err != nil { + ctx.PropertyErrorf("jacoco.include_filter", "%s", err.Error()) + } + excludes, err := jacocoFiltersToSpecs(j.properties.Jacoco.Exclude_filter) + if err != nil { + ctx.PropertyErrorf("jacoco.exclude_filter", "%s", err.Error()) + } + return jacocoFiltersToZipCommand(includes, excludes) +} + +func jacocoFiltersToZipCommand(includes, excludes []string) string { specs := "" if len(excludes) > 0 { specs += android.JoinWithPrefix(excludes, "-x") + " " } - if len(includes) > 0 { specs += strings.Join(includes, " ") } else { specs += "**/*.class" } - return specs } -func jacocoFiltersToSpecs(ctx android.ModuleContext, filters []string, property string) []string { +func jacocoFiltersToSpecs(filters []string) ([]string, error) { specs := make([]string, len(filters)) + var err error for i, f := range filters { - specs[i] = jacocoFilterToSpec(ctx, f, property) + specs[i], err = jacocoFilterToSpec(f) + if err != nil { + return nil, err + } } - return specs + return specs, nil } -func jacocoFilterToSpec(ctx android.ModuleContext, filter string, property string) string { +func jacocoFilterToSpec(filter string) (string, error) { wildcard := strings.HasSuffix(filter, "*") filter = strings.TrimSuffix(filter, "*") recursiveWildcard := wildcard && (strings.HasSuffix(filter, ".") || filter == "") if strings.ContainsRune(filter, '*') { - ctx.PropertyErrorf(property, "'*' is only supported as the last character in a filter") + return "", fmt.Errorf("'*' is only supported as the last character in a filter") } spec := strings.Replace(filter, ".", "/", -1) @@ -104,5 +115,5 @@ func jacocoFilterToSpec(ctx android.ModuleContext, filter string, property strin spec += "*.class" } - return spec + return spec, nil } diff --git a/java/jacoco_test.go b/java/jacoco_test.go new file mode 100644 index 000000000..832101712 --- /dev/null +++ b/java/jacoco_test.go @@ -0,0 +1,84 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import "testing" + +func TestJacocoFilterToSpecs(t *testing.T) { + testCases := []struct { + name, in, out string + }{ + { + name: "class wildcard", + in: "package.Class*", + out: "package/Class*.class", + }, + { + name: "package wildcard", + in: "package.*", + out: "package/**/*.class", + }, + { + name: "all wildcard", + in: "*", + out: "**/*.class", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + got, err := jacocoFilterToSpec(testCase.in) + if err != nil { + t.Error(err) + } + if got != testCase.out { + t.Errorf("expected %q got %q", testCase.out, got) + } + }) + } +} + +func TestJacocoFiltersToZipCommand(t *testing.T) { + testCases := []struct { + name string + includes, excludes []string + out string + }{ + { + name: "implicit wildcard", + includes: []string{}, + out: "**/*.class", + }, + { + name: "only include", + includes: []string{"package/Class.class"}, + out: "package/Class.class", + }, + { + name: "multiple includes", + includes: []string{"package/Class.class", "package2/Class.class"}, + out: "package/Class.class package2/Class.class", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + got := jacocoFiltersToZipCommand(testCase.includes, testCase.excludes) + if got != testCase.out { + t.Errorf("expected %q got %q", testCase.out, got) + } + }) + } +} diff --git a/java/java.go b/java/java.go index 05d38f237..e6ed931fe 100644 --- a/java/java.go +++ b/java/java.go @@ -894,7 +894,7 @@ func (j *Module) desugar(ctx android.ModuleContext, flags javaBuilderFlags, func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags, classesJar android.Path, jarName string) android.Path { - specs := j.jacocoStripSpecs(ctx) + specs := j.jacocoModuleToZipCommand(ctx) jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco", "jacoco-report-classes.jar") instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName)