blob: e6da5a65756d2a7ad68ea3369bc66a058c2b2450 [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 && ` +
Colin Cross6abc9732017-12-21 14:11:13 -080031 `${config.JavaCmd} -jar ${config.JacocoCLIJar} ` +
32 ` instrument --quiet --dest $instrumentedJar $strippedJar && ` +
Colin Crosscb933592017-11-22 13:49:43 -080033 `${config.Ziptime} $instrumentedJar && ` +
34 `${config.MergeZipsCmd} --ignore-duplicates -j $out $instrumentedJar $in`,
35 CommandDeps: []string{
36 "${config.Zip2ZipCmd}",
37 "${config.JavaCmd}",
38 "${config.JacocoCLIJar}",
39 "${config.Ziptime}",
40 "${config.MergeZipsCmd}",
41 },
42 },
43 "strippedJar", "stripSpec", "instrumentedJar")
44)
45
46func jacocoInstrumentJar(ctx android.ModuleContext, outputJar, strippedJar android.WritablePath,
47 inputJar android.Path, stripSpec string) {
48 instrumentedJar := android.PathForModuleOut(ctx, "jacoco/instrumented.jar")
49
50 ctx.Build(pctx, android.BuildParams{
51 Rule: jacoco,
52 Description: "jacoco",
53 Output: outputJar,
54 ImplicitOutput: strippedJar,
55 Input: inputJar,
56 Args: map[string]string{
57 "strippedJar": strippedJar.String(),
58 "stripSpec": stripSpec,
59 "instrumentedJar": instrumentedJar.String(),
60 },
61 })
62}
63
Colin Cross7a3139e2017-12-19 13:57:50 -080064func (j *Module) jacocoModuleToZipCommand(ctx android.ModuleContext) string {
65 includes, err := jacocoFiltersToSpecs(j.properties.Jacoco.Include_filter)
66 if err != nil {
67 ctx.PropertyErrorf("jacoco.include_filter", "%s", err.Error())
68 }
69 excludes, err := jacocoFiltersToSpecs(j.properties.Jacoco.Exclude_filter)
70 if err != nil {
71 ctx.PropertyErrorf("jacoco.exclude_filter", "%s", err.Error())
72 }
Colin Crosscb933592017-11-22 13:49:43 -080073
Colin Cross7a3139e2017-12-19 13:57:50 -080074 return jacocoFiltersToZipCommand(includes, excludes)
75}
76
77func jacocoFiltersToZipCommand(includes, excludes []string) string {
Colin Crosscb933592017-11-22 13:49:43 -080078 specs := ""
79 if len(excludes) > 0 {
Colin Crossd7deceb2017-12-19 13:59:44 -080080 specs += android.JoinWithPrefix(excludes, "-x ") + " "
Colin Crosscb933592017-11-22 13:49:43 -080081 }
Colin Crosscb933592017-11-22 13:49:43 -080082 if len(includes) > 0 {
83 specs += strings.Join(includes, " ")
84 } else {
85 specs += "**/*.class"
86 }
Colin Crosscb933592017-11-22 13:49:43 -080087 return specs
88}
89
Colin Cross7a3139e2017-12-19 13:57:50 -080090func jacocoFiltersToSpecs(filters []string) ([]string, error) {
Colin Crosscb933592017-11-22 13:49:43 -080091 specs := make([]string, len(filters))
Colin Cross7a3139e2017-12-19 13:57:50 -080092 var err error
Colin Crosscb933592017-11-22 13:49:43 -080093 for i, f := range filters {
Colin Cross7a3139e2017-12-19 13:57:50 -080094 specs[i], err = jacocoFilterToSpec(f)
95 if err != nil {
96 return nil, err
97 }
Colin Crosscb933592017-11-22 13:49:43 -080098 }
Colin Cross7a3139e2017-12-19 13:57:50 -080099 return specs, nil
Colin Crosscb933592017-11-22 13:49:43 -0800100}
101
Colin Cross7a3139e2017-12-19 13:57:50 -0800102func jacocoFilterToSpec(filter string) (string, error) {
Colin Crosscb933592017-11-22 13:49:43 -0800103 wildcard := strings.HasSuffix(filter, "*")
104 filter = strings.TrimSuffix(filter, "*")
105 recursiveWildcard := wildcard && (strings.HasSuffix(filter, ".") || filter == "")
106
107 if strings.ContainsRune(filter, '*') {
Colin Cross7a3139e2017-12-19 13:57:50 -0800108 return "", fmt.Errorf("'*' is only supported as the last character in a filter")
Colin Crosscb933592017-11-22 13:49:43 -0800109 }
110
111 spec := strings.Replace(filter, ".", "/", -1)
112
113 if recursiveWildcard {
114 spec += "**/*.class"
115 } else if wildcard {
116 spec += "*.class"
Colin Crossd7deceb2017-12-19 13:59:44 -0800117 } else {
118 spec += ".class"
Colin Crosscb933592017-11-22 13:49:43 -0800119 }
120
Colin Cross7a3139e2017-12-19 13:57:50 -0800121 return spec, nil
Colin Crosscb933592017-11-22 13:49:43 -0800122}