blob: 6e522d2083889887144398f5456183e71d40459d [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 expectations
import (
"context"
"path/filepath"
"testing"
"dawn.googlesource.com/dawn/tools/src/cmd/cts/common"
"dawn.googlesource.com/dawn/tools/src/fileutils"
"dawn.googlesource.com/dawn/tools/src/oswrapper"
"github.com/stretchr/testify/require"
)
func TestUpdateExpectations(t *testing.T) {
tests := []struct {
name string
resultsFile string
resultsContent string
testListPath string
testListContent string
expectationsPath string
expectationsContent string
expectationsFlag []string
wantErr string
wantLog string
verifyContent func(t *testing.T, fs oswrapper.FilesystemReader, path string)
generateExplicitTags bool
}{
{
name: "Success",
resultsFile: "results.txt",
resultsContent: "webgpu:test:one linux,nvidia Failure 0s false\ncore",
testListPath: "third_party/gn/webgpu-cts/test_list.txt",
testListContent: "webgpu:test:one\nwebgpu:test:two",
expectationsPath: "expectations.txt",
expectationsContent: `# BEGIN TAG HEADER
# OS
# tags: [ mac win linux android ]
# GPU
# tags: [ amd intel nvidia qualcomm ]
# Device
# tags: [ android-pixel-4 android-pixel-6 chromeos-board-amd64-generic fuchsia-board-qemu-x64 ]
# END TAG HEADER
# existing
[ mac ] webgpu:test:two: [ Failure ]
`,
expectationsFlag: []string{"expectations.txt"},
verifyContent: func(t *testing.T, fs oswrapper.FilesystemReader, path string) {
content, err := fs.ReadFile(path)
require.NoError(t, err)
text := string(content)
require.Contains(t, text, "[ linux nvidia ] webgpu:test:one: [ Failure ]")
require.Contains(t, text, "[ mac ] webgpu:test:two: [ Failure ]")
},
},
{
name: "Results Fetch Error",
resultsFile: "nonexistent.txt",
testListPath: "third_party/gn/webgpu-cts/test_list.txt",
testListContent: "webgpu:test:one",
expectationsPath: "expectations.txt",
expectationsFlag: []string{"expectations.txt"},
wantErr: "does not exist",
},
{
name: "Test List Load Error",
resultsFile: "results.txt",
resultsContent: "webgpu:test:one linux Failure 0s false\ncore",
testListPath: "nonexistent/test_list.txt",
expectationsPath: "expectations.txt",
expectationsFlag: []string{"expectations.txt"},
wantErr: "failed to load test list",
},
{
name: "Expectations Load Error",
resultsFile: "results.txt",
resultsContent: "webgpu:test:one linux Failure 0s false\ncore",
testListPath: "third_party/gn/webgpu-cts/test_list.txt",
testListContent: "webgpu:test:one\nwebgpu:test:two",
expectationsPath: "expectations.txt",
expectationsFlag: []string{"nonexistent.txt"},
wantErr: "does not exist",
},
{
name: "Expectations Validation Error",
resultsFile: "results.txt",
resultsContent: "webgpu:test:one linux Failure 0s false\ncore",
testListPath: "third_party/gn/webgpu-cts/test_list.txt",
testListContent: "webgpu:test:one",
expectationsPath: "expectations.txt",
expectationsContent: "INVALID SYNTAX",
expectationsFlag: []string{"expectations.txt"},
wantErr: "expected status",
},
{
name: "Compat Mode",
resultsFile: "results.txt",
resultsContent: "webgpu:test:compat linux,nvidia Failure 0s false\ncompat",
testListPath: "third_party/gn/webgpu-cts/test_list.txt",
testListContent: "webgpu:test:compat",
expectationsPath: "compat_expectations.txt",
expectationsContent: `# BEGIN TAG HEADER
# OS
# tags: [ mac win linux android ]
# GPU
# tags: [ amd intel nvidia qualcomm ]
# Device
# tags: [ android-pixel-4 android-pixel-6 chromeos-board-amd64-generic fuchsia-board-qemu-x64 ]
# END TAG HEADER
`,
expectationsFlag: []string{"compat_expectations.txt"},
verifyContent: func(t *testing.T, fs oswrapper.FilesystemReader, path string) {
content, err := fs.ReadFile(path)
require.NoError(t, err)
require.Contains(t, string(content), "[ linux nvidia ] webgpu:test:compat: [ Failure ]")
},
},
{
name: "Unknown Tests Removal",
resultsFile: "results.txt",
resultsContent: "webgpu:test:known linux,nvidia Failure 0s false\ncore",
testListPath: "third_party/gn/webgpu-cts/test_list.txt",
testListContent: "webgpu:test:known",
expectationsPath: "expectations.txt",
expectationsContent: `# BEGIN TAG HEADER
# OS
# tags: [ mac win linux android ]
# GPU
# tags: [ amd intel nvidia qualcomm ]
# Device
# tags: [ android-pixel-4 android-pixel-6 chromeos-board-amd64-generic fuchsia-board-qemu-x64 ]
# END TAG HEADER
webgpu:test:unknown: [ Failure ]`,
expectationsFlag: []string{"expectations.txt"},
verifyContent: func(t *testing.T, fs oswrapper.FilesystemReader, path string) {
content, err := fs.ReadFile(path)
require.NoError(t, err)
require.NotContains(t, string(content), "webgpu:test:unknown")
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
wrapper := oswrapper.CreateFSTestOSWrapper()
realWrapper := oswrapper.GetRealOSWrapper()
rootDir := fileutils.DawnRoot(realWrapper)
// Helper to write file relative to root
write := func(path, content string) {
fullPath := filepath.Join(rootDir, path)
require.NoError(t, wrapper.MkdirAll(filepath.Dir(fullPath), 0755))
require.NoError(t, wrapper.WriteFile(fullPath, []byte(content), 0666))
}
if tt.resultsContent != "" {
write(tt.resultsFile, tt.resultsContent)
}
if tt.testListContent != "" {
write(tt.testListPath, tt.testListContent)
}
if tt.expectationsContent != "" {
write(tt.expectationsPath, tt.expectationsContent)
}
c := &cmd{}
// Resolve paths to absolute for flags
absExpectations := make([]string, len(tt.expectationsFlag))
for i, p := range tt.expectationsFlag {
absExpectations[i] = filepath.Join(rootDir, p)
}
c.flags.expectations = absExpectations
if tt.resultsFile != "" {
c.flags.results.File = filepath.Join(rootDir, tt.resultsFile)
}
c.flags.verbose = true
c.flags.generateExplicitTags = tt.generateExplicitTags
ctx := context.Background()
cfg := common.Config{OsWrapper: wrapper}
write("DEPS", "") // Ensure DawnRoot detection works
err := c.Run(ctx, cfg)
if tt.wantErr != "" {
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
} else {
require.NoError(t, err)
}
if tt.verifyContent != nil {
// Check content of the first expectations file
path := filepath.Join(rootDir, tt.expectationsPath)
tt.verifyContent(t, wrapper, path)
}
})
}
}