blob: 3a1af3545701401911033b66d1ab855e64ba87ca [file] [log] [blame]
// Copyright 2025 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package expectationcoverage
import (
"bytes"
"context"
"fmt"
"reflect"
"testing"
"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
"dawn.googlesource.com/dawn/tools/src/cts/expectations"
"dawn.googlesource.com/dawn/tools/src/cts/query"
"dawn.googlesource.com/dawn/tools/src/cts/result"
"dawn.googlesource.com/dawn/tools/src/oswrapper"
"dawn.googlesource.com/dawn/tools/src/resultsdb"
"github.com/stretchr/testify/require"
)
/*******************************************************************************
* Run tests
******************************************************************************/
func createConfig(wrapper oswrapper.OSWrapper, client resultsdb.Querier) common.Config {
return common.Config{
Tests: []common.TestConfig{
{
ExecutionMode: "core",
Prefixes: []string{"core_prefix"},
},
{
ExecutionMode: "compat",
Prefixes: []string{"compat_prefix"},
},
},
OsWrapper: wrapper,
Querier: client,
}
}
func createRunSampleQueryResults() resultsdb.PrefixGroupedQueryResults {
return resultsdb.PrefixGroupedQueryResults{
"core_prefix": []resultsdb.QueryResult{
{
TestId: "core_prefix_foo",
Status: "FAIL",
Tags: []resultsdb.TagPair{
{
Key: "typ_tag",
Value: "linux",
},
},
},
{
TestId: "core_prefix_bar",
Status: "FAIL",
Tags: []resultsdb.TagPair{
{
Key: "typ_tag",
Value: "mac",
},
},
},
},
"compat_prefix": []resultsdb.QueryResult{
{
TestId: "compat_prefix_bar",
Status: "FAIL",
Tags: []resultsdb.TagPair{
{
Key: "typ_tag",
Value: "linux",
},
},
},
{
TestId: "compat_prefix_foo",
Status: "FAIL",
Tags: []resultsdb.TagPair{
{
Key: "typ_tag",
Value: "win10",
},
},
},
},
}
}
func TestRun_GetTrimmedContentFailure(t *testing.T) {
wrapper, err := common.CreateMemMapOSWrapperWithFakeDefaultPaths()
require.NoErrorf(t, err, "Error creating fake Dawn directories: %v", err)
client := resultsdb.MockBigQueryClient{}
expectationFileContent := `# BEGIN TAG HEADER
# OS
# tags: [ android linux mac win10 ]
# END TAG HEADER
crbug.com/0000 [ android ] foo
`
wrapper.WriteFile(common.DefaultExpectationsPath(wrapper), []byte(expectationFileContent), 0o700)
ctx := context.Background()
cfg := createConfig(wrapper, client)
c := cmd{}
err = c.Run(ctx, cfg)
require.ErrorContains(t, err, "/webgpu-cts/expectations.txt:6:31 error: expected status")
}
func TestRun_GetResultsFailure(t *testing.T) {
wrapper, err := common.CreateMemMapOSWrapperWithFakeDefaultPaths()
require.NoErrorf(t, err, "Error creating fake Dawn directories: %v", err)
client := resultsdb.MockBigQueryClient{}
expectationFileContent := getExpectationContentForTrimmedContentTest()
wrapper.WriteFile(common.DefaultExpectationsPath(wrapper), []byte(expectationFileContent), 0o700)
client.RecentUniqueSuppressedReturnValues = resultsdb.PrefixGroupedQueryResults{
"core_prefix": []resultsdb.QueryResult{
{
TestId: "invalid_prefix_test",
Status: "FAIL",
},
},
}
ctx := context.Background()
cfg := createConfig(wrapper, client)
c := cmd{}
err = c.Run(ctx, cfg)
require.ErrorContains(t, err,
"Test ID invalid_prefix_test did not start with core_prefix even though query should have filtered.")
}
func TestRun_SuccessCore(t *testing.T) {
wrapper, err := common.CreateMemMapOSWrapperWithFakeDefaultPaths()
require.NoErrorf(t, err, "Error creating fake Dawn directories: %v", err)
client := resultsdb.MockBigQueryClient{}
expectationFileContent := getExpectationContentForTrimmedContentTest()
wrapper.WriteFile(common.DefaultExpectationsPath(wrapper), []byte(expectationFileContent), 0o700)
client.RecentUniqueSuppressedReturnValues = createRunSampleQueryResults()
ctx := context.Background()
cfg := createConfig(wrapper, client)
c := cmd{}
err = c.Run(ctx, cfg)
require.NoErrorf(t, err, "Got error: %v", err)
}
func TestRun_SuccessCompat(t *testing.T) {
wrapper, err := common.CreateMemMapOSWrapperWithFakeDefaultPaths()
require.NoErrorf(t, err, "Error creating fake Dawn directories: %v", err)
client := resultsdb.MockBigQueryClient{}
expectationFileContent := getExpectationContentForTrimmedContentTest()
wrapper.WriteFile(common.DefaultCompatExpectationsPath(wrapper), []byte(expectationFileContent), 0o700)
client.RecentUniqueSuppressedReturnValues = createRunSampleQueryResults()
ctx := context.Background()
cfg := createConfig(wrapper, client)
c := cmd{}
c.flags.checkCompatExpectations = true
err = c.Run(ctx, cfg)
require.NoErrorf(t, err, "Got error: %v", err)
}
/*******************************************************************************
* getTrimmedContent tests
******************************************************************************/
func TestGetTrimmedContent_NonExistentFile(t *testing.T) {
wrapper := oswrapper.CreateMemMapOSWrapper()
content, err := getTrimmedContent(
"/expectations.txt",
/*individualExpectations=*/ false,
/*ignoreSkipExpectations=*/ false,
/*verbose=*/ false,
wrapper)
require.Equal(t, content, expectations.Content{})
require.ErrorContains(t, err, "open /expectations.txt: file does not exist")
}
func TestGetTrimmedContent_InvalidFile(t *testing.T) {
wrapper := oswrapper.CreateMemMapOSWrapper()
expectationFileContent := `# BEGIN TAG HEADER
# OS
# tags: [ android linux mac win10 ]
# END TAG HEADER
crbug.com/0000 [ android ] foo
`
wrapper.WriteFile("/expectations.txt", []byte(expectationFileContent), 0o700)
content, err := getTrimmedContent(
"/expectations.txt",
/*individualExpectations=*/ false,
/*ignoreSkipExpectations=*/ false,
/*verbose=*/ false,
wrapper)
require.Equal(t, content, expectations.Content{})
require.ErrorContains(t, err, "/expectations.txt:6:31 error: expected status")
}
// Error from getPermanentSkipContent not tested since there is no way to
// trigger an error there without triggering an error when parsing in
// getTrimmedContent.
func getExpectationContentForTrimmedContentTest() string {
return `# BEGIN TAG HEADER
# OS
# tags: [ android linux mac win10 ]
# END TAG HEADER
################################################################################
# Permanent Skip Expectations
################################################################################
# Permanent skips
crbug.com/0000 [ android ] foo [ Skip ]
crbug.com/0000 [ android ] bar [ Skip ]
################################################################################
# Temporary Skip Expectations
################################################################################
# Temporary skips
crbug.com/0000 [ linux ] foo [ Skip ]
crbug.com/0000 [ linux ] bar [ Skip ]
################################################################################
# Triaged/Manually Added Failures
################################################################################
# Failures 1
crbug.com/0000 [ mac ] foo [ Failure ]
crbug.com/0000 [ mac ] bar [ RetryOnFailure ]
# Failures 2
# Second line
crbug.com/0000 [ win10 ] foo [ Failure ]
crbug.com/0000 [ win10 ] bar [ Failure ]
`
}
func TestGetTrimmedContent_GroupedWithSkips(t *testing.T) {
wrapper := oswrapper.CreateMemMapOSWrapper()
expectationFileContent := getExpectationContentForTrimmedContentTest()
wrapper.WriteFile("/expectations.txt", []byte(expectationFileContent), 0o700)
content, err := getTrimmedContent(
"/expectations.txt",
/*individualExpectations=*/ false,
/*ignoreSkipExpectations=*/ false,
/*verbose=*/ false,
wrapper)
expectedChunks := []expectations.Chunk{
{
Comments: []string{"# Temporary skips"},
Expectations: expectations.Expectations{
{
Line: 19,
Bug: "crbug.com/0000",
Tags: result.NewTags("linux"),
Query: "foo",
Status: []string{"Skip"},
},
{
Line: 20,
Bug: "crbug.com/0000",
Tags: result.NewTags("linux"),
Query: "bar",
Status: []string{"Skip"},
},
},
},
{
Comments: []string{"# Failures 1"},
Expectations: expectations.Expectations{
{
Line: 27,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "foo",
Status: []string{"Failure"},
},
{
Line: 28,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "bar",
Status: []string{"RetryOnFailure"},
},
},
},
{
Comments: []string{"# Failures 2", "# Second line"},
Expectations: expectations.Expectations{
{
Line: 32,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "foo",
Status: []string{"Failure"},
},
{
Line: 33,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "bar",
Status: []string{"Failure"},
},
},
},
}
require.NoErrorf(t, err, "Got error getting trimmed content: %v", err)
require.Equal(t, expectedChunks, content.Chunks)
}
func TestGetTrimmedContent_GroupedWithoutSkips(t *testing.T) {
wrapper := oswrapper.CreateMemMapOSWrapper()
expectationFileContent := getExpectationContentForTrimmedContentTest()
wrapper.WriteFile("/expectations.txt", []byte(expectationFileContent), 0o700)
content, err := getTrimmedContent(
"/expectations.txt",
/*individualExpectations=*/ false,
/*ignoreSkipExpectations=*/ true,
/*verbose=*/ false,
wrapper)
expectedChunks := []expectations.Chunk{
{
Comments: []string{"# Failures 1"},
Expectations: expectations.Expectations{
{
Line: 27,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "foo",
Status: []string{"Failure"},
},
{
Line: 28,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "bar",
Status: []string{"RetryOnFailure"},
},
},
},
{
Comments: []string{"# Failures 2", "# Second line"},
Expectations: expectations.Expectations{
{
Line: 32,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "foo",
Status: []string{"Failure"},
},
{
Line: 33,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "bar",
Status: []string{"Failure"},
},
},
},
}
require.NoErrorf(t, err, "Got error getting trimmed content: %v", err)
require.Equal(t, expectedChunks, content.Chunks)
}
func TestGetTrimmedContent_IndividualWithSkips(t *testing.T) {
wrapper := oswrapper.CreateMemMapOSWrapper()
expectationFileContent := getExpectationContentForTrimmedContentTest()
wrapper.WriteFile("/expectations.txt", []byte(expectationFileContent), 0o700)
content, err := getTrimmedContent(
"/expectations.txt",
/*individualExpectations=*/ true,
/*ignoreSkipExpectations=*/ false,
/*verbose=*/ false,
wrapper)
expectedChunks := []expectations.Chunk{
{
Comments: []string{"# Temporary skips"},
Expectations: expectations.Expectations{
{
Line: 19,
Bug: "crbug.com/0000",
Tags: result.NewTags("linux"),
Query: "foo",
Status: []string{"Skip"},
},
},
},
{
Comments: []string{"# Temporary skips"},
Expectations: expectations.Expectations{
{
Line: 20,
Bug: "crbug.com/0000",
Tags: result.NewTags("linux"),
Query: "bar",
Status: []string{"Skip"},
},
},
},
{
Comments: []string{"# Failures 1"},
Expectations: expectations.Expectations{
{
Line: 27,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "foo",
Status: []string{"Failure"},
},
},
},
{
Comments: []string{"# Failures 1"},
Expectations: expectations.Expectations{
{
Line: 28,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "bar",
Status: []string{"RetryOnFailure"},
},
},
},
{
Comments: []string{"# Failures 2", "# Second line"},
Expectations: expectations.Expectations{
{
Line: 32,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "foo",
Status: []string{"Failure"},
},
},
},
{
Comments: []string{"# Failures 2", "# Second line"},
Expectations: expectations.Expectations{
{
Line: 33,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "bar",
Status: []string{"Failure"},
},
},
},
}
require.NoErrorf(t, err, "Got error getting trimmed content: %v", err)
require.Equal(t, expectedChunks, content.Chunks)
}
func TestGetTrimmedContent_IndividualWithoutSkips(t *testing.T) {
wrapper := oswrapper.CreateMemMapOSWrapper()
expectationFileContent := getExpectationContentForTrimmedContentTest()
wrapper.WriteFile("/expectations.txt", []byte(expectationFileContent), 0o700)
content, err := getTrimmedContent(
"/expectations.txt",
/*individualExpectations=*/ true,
/*ignoreSkipExpectations=*/ true,
/*verbose=*/ false,
wrapper)
expectedChunks := []expectations.Chunk{
{
Comments: []string{"# Failures 1"},
Expectations: expectations.Expectations{
{
Line: 27,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "foo",
Status: []string{"Failure"},
},
},
},
{
Comments: []string{"# Failures 1"},
Expectations: expectations.Expectations{
{
Line: 28,
Bug: "crbug.com/0000",
Tags: result.NewTags("mac"),
Query: "bar",
Status: []string{"RetryOnFailure"},
},
},
},
{
Comments: []string{"# Failures 2", "# Second line"},
Expectations: expectations.Expectations{
{
Line: 32,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "foo",
Status: []string{"Failure"},
},
},
},
{
Comments: []string{"# Failures 2", "# Second line"},
Expectations: expectations.Expectations{
{
Line: 33,
Bug: "crbug.com/0000",
Tags: result.NewTags("win10"),
Query: "bar",
Status: []string{"Failure"},
},
},
},
}
require.NoErrorf(t, err, "Got error getting trimmed content: %v", err)
require.Equal(t, expectedChunks, content.Chunks)
}
/*******************************************************************************
* getPermanentSkipContent tests
******************************************************************************/
func TestGetPermanentSkipContent(t *testing.T) {
tests := []struct {
name string
content string
want []expectations.Chunk
wantErr bool
wantErrMsg string
}{
{ /////////////////////////////////////////////////////////////////////////
name: "Success",
content: `# BEGIN TAG HEADER
# OS
# tags: [ android linux mac win10 ]
# END TAG HEADER
# Comment
crbug.com/1234 [ android ] foo [ Skip ]
################################################################################
# Temporary Skip Expectations
################################################################################
crbug.com/2345 [ linux ] bar [ Skip ]
`,
want: []expectations.Chunk{
expectations.Chunk{
Comments: []string{
"# Comment",
},
Expectations: []expectations.Expectation{
expectations.Expectation{
Line: 7,
Bug: "crbug.com/1234",
Tags: result.NewTags("android"),
Query: "foo",
Status: []string{
"Skip",
},
},
},
},
},
wantErr: false,
wantErrMsg: "",
},
{ /////////////////////////////////////////////////////////////////////////
name: "No temporary skip header",
content: `# BEGIN TAG HEADER
# OS
# tags: [ android linux mac win10 ]
# END TAG HEADER
# Comment
crbug.com/1234 [ android ] foo [ Skip ]
crbug.com/2345 [ linux ] bar [ Skip ]
`,
want: nil,
wantErr: false,
wantErrMsg: "",
},
{ /////////////////////////////////////////////////////////////////////////
name: "Parse error",
content: `# BEGIN TAG HEADER
# OS
# tags: [ android linux mac win10 ]
# END TAG HEADER
# Comment
crbug.com/1234 [ android ] foo
################################################################################
# Temporary Skip Expectations
################################################################################
crbug.com/2345 [ linux ] bar [ Skip ]
`,
want: nil,
wantErr: true,
wantErrMsg: "expectations.txt:7:31 error: expected status",
},
}
for _, testCase := range tests {
t.Run(testCase.name, func(t *testing.T) {
content, err := getPermanentSkipContent("expectations.txt", testCase.content)
if (err != nil) != testCase.wantErr {
t.Errorf("getPermanentSkipContent() error = %v, wantErr %v", err, testCase.wantErr)
}
if testCase.wantErr && err.Error() != testCase.wantErrMsg {
t.Errorf("getPermanentSkipContent() errorMsg = %v, wantErrMsg %v", err.Error(), testCase.wantErrMsg)
return
}
if !reflect.DeepEqual(content.Chunks, testCase.want) {
t.Errorf("getPermanentSkipContent() = %v, want %v", content.Chunks, testCase.want)
return
}
})
}
}
/*******************************************************************************
* getChunksOrderedByCoverageLoss tests
******************************************************************************/
func TestGetChunksOrderedByCoverageLoss_FewResults(t *testing.T) {
content := expectations.Content{
Chunks: []expectations.Chunk{
// Should not apply to anything.
{
Expectations: expectations.Expectations{
{
Query: "fake_test",
Tags: result.NewTags("android"),
},
{
Query: "real_test",
Tags: result.NewTags("fake_tag"),
},
},
},
// Should apply to everything due to the first expectation.
{
Expectations: expectations.Expectations{
{
Query: "*",
Tags: result.NewTags(),
},
{
Query: "fake_test",
Tags: result.NewTags("android"),
},
},
},
// Should apply to everything due to the second expectation.
{
Expectations: expectations.Expectations{
{
Query: "fake_test",
Tags: result.NewTags("android"),
},
{
Query: "*",
Tags: result.NewTags(),
},
},
},
// Should only apply to a single result.
{
Expectations: expectations.Expectations{
{
Query: "real_test_2",
Tags: result.NewTags("android"),
},
},
},
// Should apply to all Android results, and thus be fairly high up.
{
Expectations: expectations.Expectations{
{
Query: "*",
Tags: result.NewTags("android"),
},
},
},
// Should apply to all Linux results, and thus should be below the
// Android one.
{
Expectations: expectations.Expectations{
{
Query: "*",
Tags: result.NewTags("linux"),
},
},
},
// Should also apply to all Linux results, but should not end up double
// counting.
{
Expectations: expectations.Expectations{
{
Query: "real_*",
Tags: result.NewTags("linux"),
},
{
Query: "real_test_1",
Tags: result.NewTags("linux"),
},
{
Query: "real_test_2",
Tags: result.NewTags("linux"),
},
},
},
},
}
uniqueResults := result.List{
{
Query: query.Parse("real_test_1"),
Tags: result.NewTags("android"),
},
{
Query: query.Parse("real_test_2"),
Tags: result.NewTags("android"),
},
{
Query: query.Parse("real_test_3"),
Tags: result.NewTags("android"),
},
{
Query: query.Parse("real_test_1"),
Tags: result.NewTags("linux"),
},
{
Query: query.Parse("real_test_2"),
Tags: result.NewTags("linux"),
},
}
expectedChunkCounts := []ChunkWithCounter{
{
Chunk: &content.Chunks[1],
Count: 5,
},
{
Chunk: &content.Chunks[2],
Count: 5,
},
{
Chunk: &content.Chunks[4],
Count: 3,
},
{
Chunk: &content.Chunks[5],
Count: 2,
},
{
Chunk: &content.Chunks[6],
Count: 2,
},
{
Chunk: &content.Chunks[3],
Count: 1,
},
{
Chunk: &content.Chunks[0],
Count: 0,
},
}
actualChunkCounts := getChunksOrderedByCoverageLoss(&content, &uniqueResults)
require.Equal(t, expectedChunkCounts, actualChunkCounts)
}
func TestGetChunksOrderedByCoverageLoss_ManyResults(t *testing.T) {
// This is primarily to exercise code when there are multiple subworkers,
// which requires a large number of results.
content := expectations.Content{
Chunks: []expectations.Chunk{
{
Expectations: expectations.Expectations{
{
Query: "*",
Tags: result.NewTags("android"),
},
},
},
{
Expectations: expectations.Expectations{
{
Query: "*",
Tags: result.NewTags("linux"),
},
},
},
},
}
uniqueResults := result.List{}
for i := 0; i < maxResultsPerWorker*2; i++ {
r := result.Result{
Query: query.Parse(fmt.Sprintf("real_test_%d", i)),
Tags: result.NewTags("android"),
}
uniqueResults = append(uniqueResults, r)
if i%2 == 0 {
r = result.Result{
Query: query.Parse(fmt.Sprintf("real_test_%d", i)),
Tags: result.NewTags("linux"),
}
uniqueResults = append(uniqueResults, r)
}
}
expectedChunkCounts := []ChunkWithCounter{
{
Chunk: &content.Chunks[0],
Count: maxResultsPerWorker * 2,
},
{
Chunk: &content.Chunks[1],
Count: maxResultsPerWorker,
},
}
actualChunkCounts := getChunksOrderedByCoverageLoss(&content, &uniqueResults)
require.Equal(t, expectedChunkCounts, actualChunkCounts)
}
/*******************************************************************************
* outputResults tests
******************************************************************************/
func getOutputResultsOrderedChunks() []ChunkWithCounter {
chunks := []expectations.Chunk{
{
Comments: []string{"# Linux"},
Expectations: expectations.Expectations{
{
Line: 5,
Bug: "crbug.com/1234",
Tags: result.NewTags("linux"),
Query: "real_test_1",
Status: []string{"Failure"},
Comment: "# trailing comment",
},
{
Line: 6,
Bug: "crbug.com/2345",
Tags: result.NewTags("linux"),
Query: "real_test_2",
Status: []string{"Failure"},
},
},
},
{
Comments: []string{"# Android", "# Second comment line"},
Expectations: expectations.Expectations{
{
Line: 10,
Bug: "crbug.com/3456",
Tags: result.NewTags("android"),
Query: "real_test_*",
Status: []string{"Failure"},
},
},
},
}
return []ChunkWithCounter{
{
Chunk: &chunks[1],
Count: 10,
},
{
Chunk: &chunks[0],
Count: 5,
},
}
}
func TestOutputResults(t *testing.T) {
tests := []struct {
name string
maxChunksToOutput int
individualExpectations bool
expectedOutput string
}{
{
name: "Output all as chunks",
maxChunksToOutput: 0,
individualExpectations: false,
expectedOutput: `
Complete output:
Comment: # Android
# Second comment line
First expectation: crbug.com/3456 [ android ] real_test_* [ Failure ]
Line number: 10
Affected 10 test results
Comment: # Linux
First expectation: crbug.com/1234 [ linux ] real_test_1 [ Failure ] # trailing comment
Line number: 5
Affected 5 test results
`,
},
{
name: "Output all as individual expectations",
maxChunksToOutput: 0,
individualExpectations: true,
expectedOutput: `
Complete output:
Comment: # Android
# Second comment line
Expectation: crbug.com/3456 [ android ] real_test_* [ Failure ]
Line number: 10
Affected 10 test results
Comment: # Linux
Expectation: crbug.com/1234 [ linux ] real_test_1 [ Failure ] # trailing comment
Line number: 5
Affected 5 test results
`,
},
{
name: "Output one as chunk",
maxChunksToOutput: 1,
individualExpectations: false,
expectedOutput: `
Top 1 chunks contributing to test coverage loss:
Comment: # Android
# Second comment line
First expectation: crbug.com/3456 [ android ] real_test_* [ Failure ]
Line number: 10
Affected 10 test results
`,
},
{
name: "Output one as individual expectations",
maxChunksToOutput: 1,
individualExpectations: true,
expectedOutput: `
Top 1 individual expectations contributing to test coverage loss:
Comment: # Android
# Second comment line
Expectation: crbug.com/3456 [ android ] real_test_* [ Failure ]
Line number: 10
Affected 10 test results
`,
},
}
for _, testCase := range tests {
t.Run(testCase.name, func(t *testing.T) {
buffer := bytes.Buffer{}
outputResults(
getOutputResultsOrderedChunks(),
testCase.maxChunksToOutput,
testCase.individualExpectations,
&buffer)
require.Equal(t, testCase.expectedOutput, buffer.String())
})
}
}