• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2022 The Bazel Authors. 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 lcov_coverage_test
16
17import (
18	"io/ioutil"
19	"path/filepath"
20	"strings"
21	"testing"
22
23	"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
24)
25
26func TestMain(m *testing.M) {
27	bazel_testing.TestMain(m, bazel_testing.Args{
28		Main: `
29-- src/BUILD.bazel --
30load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
31
32go_library(
33    name = "lib",
34    srcs = ["lib.go"],
35    importpath = "example.com/lib",
36    deps = [":other_lib"],
37)
38
39go_library(
40    name = "other_lib",
41    srcs = ["other_lib.go"],
42    importpath = "example.com/other_lib",
43)
44
45go_test(
46    name = "lib_test",
47    srcs = ["lib_test.go"],
48    deps = [":lib"],
49)
50
51java_binary(
52    name = "Tool",
53    srcs = ["Tool.java"],
54)
55
56go_test(
57    name = "lib_with_tool_test",
58    srcs = ["lib_with_tool_test.go"],
59    data = [":Tool"],
60    deps = [":lib"],
61)
62-- src/lib.go --
63package lib
64
65import (
66	"strings"
67
68	"example.com/other_lib"
69)
70
71func HelloFromLib(informal bool) string {
72	var greetings []string
73	if informal {
74		greetings = []string{"Hey there, other_lib!"}
75	} else {
76		greetings = []string{"Good morning, other_lib!"}
77	}
78	greetings = append(greetings, other_lib.HelloOtherLib(informal))
79	return strings.Join(greetings, "\n")
80}
81-- src/other_lib.go --
82package other_lib
83
84func HelloOtherLib(informal bool) string {
85	if informal {
86		return "Hey there, other_lib!"
87	}
88	return "Good morning, other_lib!"
89}
90-- src/lib_test.go --
91package lib_test
92
93import (
94	"strings"
95	"testing"
96
97	"example.com/lib"
98)
99
100func TestLib(t *testing.T) {
101	if !strings.Contains(lib.HelloFromLib(false), "\n") {
102		t.Error("Expected a newline in the output")
103	}
104}
105-- src/Tool.java --
106public class Tool {
107  public static void main(String[] args) {
108    if (args.length != 0) {
109      System.err.println("Expected no arguments");
110      System.exit(1);
111    }
112    System.err.println("Hello, world!");
113  }
114}
115-- src/lib_with_tool_test.go --
116package lib_test
117
118import (
119	"os/exec"
120	"path/filepath"
121	"strings"
122	"testing"
123
124	"example.com/lib"
125)
126
127func TestLib(t *testing.T) {
128	if !strings.Contains(lib.HelloFromLib(false), "\n") {
129		t.Error("Expected a newline in the output")
130	}
131}
132
133func TestTool(t *testing.T) {
134	err := exec.Command("." + string(filepath.Separator) + "Tool").Run()
135	if err != nil {
136		t.Error(err)
137	}
138}
139
140`,
141	})
142}
143
144func TestLcovCoverage(t *testing.T) {
145	t.Run("without-race", func(t *testing.T) {
146		testLcovCoverage(t)
147	})
148
149	t.Run("with-race", func(t *testing.T) {
150		testLcovCoverage(t, "--@io_bazel_rules_go//go/config:race")
151	})
152}
153
154func testLcovCoverage(t *testing.T, extraArgs ...string) {
155	args := append([]string{
156		"coverage",
157		"--combined_report=lcov",
158		"//src:lib_test",
159	}, extraArgs...)
160
161	if err := bazel_testing.RunBazel(args...); err != nil {
162		t.Fatal(err)
163	}
164
165	individualCoveragePath := filepath.FromSlash("bazel-testlogs/src/lib_test/coverage.dat")
166	individualCoverageData, err := ioutil.ReadFile(individualCoveragePath)
167	if err != nil {
168		t.Fatal(err)
169	}
170	for _, expectedIndividualCoverage := range expectedGoCoverage {
171		if !strings.Contains(string(individualCoverageData), expectedIndividualCoverage) {
172			t.Errorf(
173				"%s: does not contain:\n\n%s\nactual content:\n\n%s",
174				individualCoveragePath,
175				expectedIndividualCoverage,
176				string(individualCoverageData),
177			)
178		}
179	}
180
181	combinedCoveragePath := filepath.FromSlash("bazel-out/_coverage/_coverage_report.dat")
182	combinedCoverageData, err := ioutil.ReadFile(combinedCoveragePath)
183	if err != nil {
184		t.Fatal(err)
185	}
186	for _, include := range []string{
187		"SF:src/lib.go\n",
188		"SF:src/other_lib.go\n",
189	} {
190		if !strings.Contains(string(combinedCoverageData), include) {
191			t.Errorf("%s: does not contain %q\n", combinedCoverageData, include)
192		}
193	}
194}
195
196func TestLcovCoverageWithTool(t *testing.T) {
197	args := append([]string{
198		"coverage",
199		"--combined_report=lcov",
200		"//src:lib_with_tool_test",
201	})
202
203	if err := bazel_testing.RunBazel(args...); err != nil {
204		t.Fatal(err)
205	}
206
207	individualCoveragePath := filepath.FromSlash("bazel-testlogs/src/lib_with_tool_test/coverage.dat")
208	individualCoverageData, err := ioutil.ReadFile(individualCoveragePath)
209	if err != nil {
210		t.Fatal(err)
211	}
212	expectedCoverage := append(expectedGoCoverage, expectedToolCoverage)
213	for _, expected := range expectedCoverage {
214		if !strings.Contains(string(individualCoverageData), expected) {
215			t.Errorf(
216				"%s: does not contain:\n\n%s\nactual content:\n\n%s",
217				individualCoveragePath,
218				expected,
219				string(individualCoverageData),
220			)
221		}
222	}
223
224	combinedCoveragePath := filepath.FromSlash("bazel-out/_coverage/_coverage_report.dat")
225	combinedCoverageData, err := ioutil.ReadFile(combinedCoveragePath)
226	if err != nil {
227		t.Fatal(err)
228	}
229	for _, include := range []string{
230		"SF:src/lib.go\n",
231		"SF:src/other_lib.go\n",
232		"SF:src/Tool.java\n",
233	} {
234		if !strings.Contains(string(combinedCoverageData), include) {
235			t.Errorf("%s: does not contain %q\n", combinedCoverageData, include)
236		}
237	}
238}
239
240var expectedGoCoverage = []string{
241	`SF:src/other_lib.go
242FNF:0
243FNH:0
244DA:3,1
245DA:4,1
246DA:5,0
247DA:6,0
248DA:7,1
249LH:3
250LF:5
251end_of_record
252`,
253	`SF:src/lib.go
254FNF:0
255FNH:0
256DA:9,1
257DA:10,1
258DA:11,1
259DA:12,0
260DA:13,1
261DA:14,1
262DA:15,1
263DA:16,1
264DA:17,1
265LH:8
266LF:9
267end_of_record
268`}
269
270const expectedToolCoverage = `SF:src/Tool.java
271FN:1,Tool::<init> ()V
272FN:3,Tool::main ([Ljava/lang/String;)V
273FNDA:0,Tool::<init> ()V
274FNDA:1,Tool::main ([Ljava/lang/String;)V
275FNF:2
276FNH:1
277BRDA:3,0,0,1
278BRDA:3,0,1,0
279BRF:2
280BRH:1
281DA:1,0
282DA:3,1
283DA:4,0
284DA:5,0
285DA:7,1
286DA:8,1
287LH:3
288LF:6
289end_of_record
290`
291