Skip to content

Commit cda1a20

Browse files
bsheedy-workDawn LUCI CQ
authored andcommitted
Add idlgen run tests
Adds test coverage for //tools/src/cmd/idlgen's run function. More specific tests for underlying helper functions will be added in follow-up CLs. Also fixes a found issue where there was code to support outputting to stdout, but it was unreachable since the --output argument was treated as required. Bug: 344014313 Change-Id: Ibb341bf73ad107ed98f457ca44202031f0c474b4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/282857 Reviewed-by: dan sinclair <[email protected]> Auto-Submit: Brian Sheedy <[email protected]> Commit-Queue: Brian Sheedy <[email protected]>
1 parent a6ca291 commit cda1a20

File tree

2 files changed

+194
-1
lines changed

2 files changed

+194
-1
lines changed

tools/src/cmd/idlgen/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func run(args []string, osWrapper oswrapper.OSWrapper) error {
7575
idlFiles := flagSet.Args()
7676

7777
// Check all required arguments are provided
78-
if templatePath == "" || outputPath == "" || len(idlFiles) == 0 {
78+
if templatePath == "" || len(idlFiles) == 0 {
7979
return showUsage()
8080
}
8181

tools/src/cmd/idlgen/main_test.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
// Copyright 2026 The Dawn & Tint Authors
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions are met:
5+
//
6+
// 1. Redistributions of source code must retain the above copyright notice, this
7+
// list of conditions and the following disclaimer.
8+
//
9+
// 2. Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
//
13+
// 3. Neither the name of the copyright holder nor the names of its
14+
// contributors may be used to endorse or promote products derived from
15+
// this software without specific prior written permission.
16+
//
17+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21+
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24+
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25+
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27+
28+
package main
29+
30+
import (
31+
"testing"
32+
33+
"dawn.googlesource.com/dawn/tools/src/oswrapper"
34+
"github.com/stretchr/testify/require"
35+
)
36+
37+
func TestRun_MissingArgs(t *testing.T) {
38+
tests := []struct {
39+
name string
40+
args []string
41+
}{
42+
{
43+
name: "No args",
44+
args: []string{},
45+
},
46+
{
47+
name: "Missing template",
48+
args: []string{"--output=out.go", "input.idl"},
49+
},
50+
{
51+
name: "Missing input file",
52+
args: []string{"--template=tmpl.go", "--output=out.go"},
53+
},
54+
}
55+
56+
for _, tt := range tests {
57+
t.Run(tt.name, func(t *testing.T) {
58+
wrapper := oswrapper.CreateFSTestOSWrapper()
59+
err := run(tt.args, wrapper)
60+
require.ErrorContains(t, err, "idlgen is a tool used to generate code")
61+
})
62+
}
63+
}
64+
65+
func TestRun_OutputToStdout(t *testing.T) {
66+
wrapper := oswrapper.CreateFSTestOSWrapper()
67+
require.NoError(t, wrapper.WriteFile("template.tmpl", []byte("{{.}}"), 0644))
68+
require.NoError(t, wrapper.WriteFile("test.idl", []byte("interface Test {}; interface GPUDevice {};"), 0644))
69+
70+
args := []string{"--template=template.tmpl", "test.idl"}
71+
err := run(args, wrapper)
72+
require.NoError(t, err)
73+
}
74+
75+
func TestRun_OutputToFile(t *testing.T) {
76+
wrapper := oswrapper.CreateFSTestOSWrapper()
77+
require.NoError(t, wrapper.WriteFile("template.tmpl", []byte("{{range .Declarations}}{{.Name}} {{end}}"), 0644))
78+
require.NoError(t, wrapper.WriteFile("test.idl", []byte("interface Test {}; interface GPUDevice {};"), 0644))
79+
80+
outputPath := "subdir/out.txt"
81+
args := []string{"--template=template.tmpl", "--output=" + outputPath, "test.idl"}
82+
err := run(args, wrapper)
83+
require.NoError(t, err)
84+
85+
// Verify file exists and has content
86+
content, err := wrapper.ReadFile(outputPath)
87+
require.NoError(t, err)
88+
require.Contains(t, string(content), "Test GPUDevice")
89+
}
90+
91+
func TestRun_OutputDirectoryCreationFailure(t *testing.T) {
92+
wrapper := oswrapper.CreateFSTestOSWrapper()
93+
require.NoError(t, wrapper.WriteFile("template.tmpl", []byte("{{.}}"), 0644))
94+
require.NoError(t, wrapper.WriteFile("test.idl", []byte("interface Test {};"), 0644))
95+
96+
// Create a file named "subdir" to block directory creation
97+
require.NoError(t, wrapper.WriteFile("subdir", []byte("i am a file"), 0644))
98+
99+
outputPath := "subdir/out.txt"
100+
args := []string{"--template=template.tmpl", "--output=" + outputPath, "test.idl"}
101+
err := run(args, wrapper)
102+
require.Error(t, err)
103+
require.ErrorContains(t, err, "failed to create output directory")
104+
}
105+
106+
func TestRun_OutputFileCreationFailure(t *testing.T) {
107+
wrapper := oswrapper.CreateFSTestOSWrapper()
108+
require.NoError(t, wrapper.WriteFile("template.tmpl", []byte("{{.}}"), 0644))
109+
require.NoError(t, wrapper.WriteFile("test.idl", []byte("interface Test {};"), 0644))
110+
111+
outputPath := "out.txt"
112+
// Create a directory at the output path to cause Create to fail
113+
require.NoError(t, wrapper.Mkdir(outputPath, 0755))
114+
115+
args := []string{"--template=template.tmpl", "--output=" + outputPath, "test.idl"}
116+
err := run(args, wrapper)
117+
require.Error(t, err)
118+
require.ErrorContains(t, err, "failed to open output file")
119+
}
120+
121+
func TestRun_TemplateReadFailure(t *testing.T) {
122+
wrapper := oswrapper.CreateFSTestOSWrapper()
123+
// Do not create the template file
124+
125+
require.NoError(t, wrapper.WriteFile("test.idl", []byte("interface Test {};"), 0644))
126+
127+
args := []string{"--template=template.tmpl", "test.idl"}
128+
err := run(args, wrapper)
129+
require.ErrorContains(t, err, "failed to open template file")
130+
}
131+
132+
func TestRun_IDLReadFailure(t *testing.T) {
133+
wrapper := oswrapper.CreateFSTestOSWrapper()
134+
require.NoError(t, wrapper.WriteFile("template.tmpl", []byte("{{.}}"), 0644))
135+
136+
// Provide a non-existent IDL file
137+
args := []string{"--template=template.tmpl", "missing.idl"}
138+
err := run(args, wrapper)
139+
require.ErrorContains(t, err, "failed to open file 'missing.idl'")
140+
}
141+
142+
func TestRun_IDLParseFailure(t *testing.T) {
143+
wrapper := oswrapper.CreateFSTestOSWrapper()
144+
require.NoError(t, wrapper.WriteFile("template.tmpl", []byte("{{.}}"), 0644))
145+
// Provide invalid IDL content
146+
require.NoError(t, wrapper.WriteFile("invalid.idl", []byte("this is definitely not valid idl"), 0644))
147+
148+
args := []string{"--template=template.tmpl", "invalid.idl"}
149+
err := run(args, wrapper)
150+
require.ErrorContains(t, err, "errors found while parsing invalid.idl")
151+
}
152+
153+
func TestRun_TemplateParseFailure(t *testing.T) {
154+
wrapper := oswrapper.CreateFSTestOSWrapper()
155+
// Provide invalid template content (unclosed action)
156+
require.NoError(t, wrapper.WriteFile("invalid.tmpl", []byte("{{.Name"), 0644))
157+
require.NoError(t, wrapper.WriteFile("test.idl", []byte("interface Test {}; interface GPUDevice {};"), 0644))
158+
159+
args := []string{"--template=invalid.tmpl", "test.idl"}
160+
err := run(args, wrapper)
161+
require.ErrorContains(t, err, "failed to parse template file")
162+
}
163+
164+
func TestRun_SuccessfulExecution(t *testing.T) {
165+
wrapper := oswrapper.CreateFSTestOSWrapper()
166+
167+
// A simple template that iterates over declarations and prints their names
168+
templateContent := `{{range .Declarations}}{{.Name}};{{end}}`
169+
require.NoError(t, wrapper.WriteFile("template.tmpl", []byte(templateContent), 0644))
170+
171+
// A simple IDL file. GPUDevice is required to avoid a panic in the patch function.
172+
idlContent := `
173+
interface MyInterface {
174+
void myMethod();
175+
};
176+
interface GPUDevice {};
177+
`
178+
require.NoError(t, wrapper.WriteFile("test.idl", []byte(idlContent), 0644))
179+
180+
outputPath := "output.txt"
181+
args := []string{"--template=template.tmpl", "--output=" + outputPath, "test.idl"}
182+
183+
err := run(args, wrapper)
184+
require.NoError(t, err)
185+
186+
// Verify the output content
187+
content, err := wrapper.ReadFile(outputPath)
188+
require.NoError(t, err)
189+
190+
outputStr := string(content)
191+
require.Contains(t, outputStr, "File generated by tools/cmd/idlgen.go")
192+
require.Contains(t, outputStr, "\n\nMyInterface;GPUDevice;")
193+
}

0 commit comments

Comments
 (0)