blob: 59f2fd3afd67071a9a051197865d9f47b638678b [file] [log] [blame]
Colin Crosscb933592017-11-22 13:49:43 -08001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17// Rules for instrumenting classes using jacoco
18
19import (
Colin Cross7a3139e2017-12-19 13:57:50 -080020 "fmt"
Colin Crosscb933592017-11-22 13:49:43 -080021 "strings"
22
23 "github.com/google/blueprint"
24
25 "android/soong/android"
26)
27
28var (
29 jacoco = pctx.AndroidStaticRule("jacoco", blueprint.RuleParams{
30 Command: `${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` +
31 `${config.JavaCmd} -jar ${config.JacocoCLIJar} instrument -quiet -dest $instrumentedJar $strippedJar && ` +
32 `${config.Ziptime} $instrumentedJar && ` +
33 `${config.MergeZipsCmd} --ignore-duplicates -j $out $instrumentedJar $in`,
34 CommandDeps: []string{
35 "${config.Zip2ZipCmd}",
36 "${config.JavaCmd}",
37 "${config.JacocoCLIJar}",
38 "${config.Ziptime}",
39 "${config.MergeZipsCmd}",
40 },
41 },
42 "strippedJar", "stripSpec", "instrumentedJar")
43)
44
45func jacocoInstrumentJar(ctx android.ModuleContext, outputJar, strippedJar android.WritablePath,
46 inputJar android.Path, stripSpec string) {
47 instrumentedJar := android.PathForModuleOut(ctx, "jacoco/instrumented.jar")
48
49 ctx.Build(pctx, android.BuildParams{
50 Rule: jacoco,
51 Description: "jacoco",
52 Output: outputJar,
53 ImplicitOutput: strippedJar,
54 Input: inputJar,
55 Args: map[string]string{
56 "strippedJar": strippedJar.String(),
57 "stripSpec": stripSpec,
58 "instrumentedJar": instrumentedJar.String(),
59 },
60 })
61}
62
Colin Cross7a3139e2017-12-19 13:57:50 -080063func (j *Module) jacocoModuleToZipCommand(ctx android.ModuleContext) string {
64 includes, err := jacocoFiltersToSpecs(j.properties.Jacoco.Include_filter)
65 if err != nil {
66 ctx.PropertyErrorf("jacoco.include_filter", "%s", err.Error())
67 }
68 excludes, err := jacocoFiltersToSpecs(j.properties.Jacoco.Exclude_filter)
69 if err != nil {
70 ctx.PropertyErrorf("jacoco.exclude_filter", "%s", err.Error())
71 }
Colin Crosscb933592017-11-22 13:49:43 -080072
Colin Cross7a3139e2017-12-19 13:57:50 -080073 return jacocoFiltersToZipCommand(includes, excludes)
74}
75
76func jacocoFiltersToZipCommand(includes, excludes []string) string {
Colin Crosscb933592017-11-22 13:49:43 -080077 specs := ""
78 if len(excludes) > 0 {
Colin Crossd7deceb2017-12-19 13:59:44 -080079 specs += android.JoinWithPrefix(excludes, "-x ") + " "
Colin Crosscb933592017-11-22 13:49:43 -080080 }
Colin Crosscb933592017-11-22 13:49:43 -080081 if len(includes) > 0 {
82 specs += strings.Join(includes, " ")
83 } else {
84 specs += "**/*.class"
85 }
Colin Crosscb933592017-11-22 13:49:43 -080086 return specs
87}
88
Colin Cross7a3139e2017-12-19 13:57:50 -080089func jacocoFiltersToSpecs(filters []string) ([]string, error) {
Colin Crosscb933592017-11-22 13:49:43 -080090 specs := make([]string, len(filters))
Colin Cross7a3139e2017-12-19 13:57:50 -080091 var err error
Colin Crosscb933592017-11-22 13:49:43 -080092 for i, f := range filters {
Colin Cross7a3139e2017-12-19 13:57:50 -080093 specs[i], err = jacocoFilterToSpec(f)
94 if err != nil {
95 return nil, err
96 }
Colin Crosscb933592017-11-22 13:49:43 -080097 }
Colin Cross7a3139e2017-12-19 13:57:50 -080098 return specs, nil
Colin Crosscb933592017-11-22 13:49:43 -080099}
100
Colin Cross7a3139e2017-12-19 13:57:50 -0800101func jacocoFilterToSpec(filter string) (string, error) {
Colin Crosscb933592017-11-22 13:49:43 -0800102 wildcard := strings.HasSuffix(filter, "*")
103 filter = strings.TrimSuffix(filter, "*")
104 recursiveWildcard := wildcard && (strings.HasSuffix(filter, ".") || filter == "")
105
106 if strings.ContainsRune(filter, '*') {
Colin Cross7a3139e2017-12-19 13:57:50 -0800107 return "", fmt.Errorf("'*' is only supported as the last character in a filter")
Colin Crosscb933592017-11-22 13:49:43 -0800108 }
109
110 spec := strings.Replace(filter, ".", "/", -1)
111
112 if recursiveWildcard {
113 spec += "**/*.class"
114 } else if wildcard {
115 spec += "*.class"
Colin Crossd7deceb2017-12-19 13:59:44 -0800116 } else {
117 spec += ".class"
Colin Crosscb933592017-11-22 13:49:43 -0800118 }
119
Colin Cross7a3139e2017-12-19 13:57:50 -0800120 return spec, nil
Colin Crosscb933592017-11-22 13:49:43 -0800121}