github.com/distbuild/reclient@v0.0.0-20240401075343-3de72e395564/internal/pkg/inputprocessor/action/clangcl/flagsparser_test.go (about) 1 // Copyright 2023 Google LLC 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 15 package clangcl 16 17 import ( 18 "context" 19 "path/filepath" 20 "testing" 21 22 "github.com/bazelbuild/reclient/internal/pkg/execroot" 23 "github.com/bazelbuild/reclient/internal/pkg/inputprocessor/flags" 24 25 "github.com/google/go-cmp/cmp" 26 "github.com/google/go-cmp/cmp/cmpopts" 27 ) 28 29 const ( 30 fakeExecRoot = "fake" 31 ) 32 33 func TestParseFlags(t *testing.T) { 34 er, cleanup := execroot.Setup(t, nil) 35 defer cleanup() 36 tests := []struct { 37 name string 38 command []string 39 workingDir string 40 files map[string][]byte 41 want *flags.CommandFlags 42 }{ 43 { 44 name: "chromium clang-cl with a simple rsp file", 45 workingDir: "out/Release", 46 files: map[string][]byte{ 47 filepath.Join("out", "Release", "foo", "args.rsp"): []byte("simple_input.txt\nmore_inputs.txt\n"), 48 filepath.Join("out", "Release", "simple_input.txt"): []byte("put filename in rsp file is a hacky way to upload a random file to RBE"), 49 filepath.Join("out", "Release", "more_inputs.txt"): []byte("you can upload more than one file to RBE with rsp file"), 50 }, 51 command: []string{ 52 "../../third_party/llvm-build/Release+Asserts/bin/clang-cl.exe", 53 "/nologo", 54 "/showIncludes:user", 55 `-imsvc..\..\third_party\depot_tools\win_toolchain\vs_files\a687d8e2e4114d9015eb550e1b156af21381faac\win_sdk\Include\10.0.19041.0\um`, 56 `-DCR_CLANG_REVISION="n358615-fb1aa286-3"`, 57 `-I../..`, 58 `-fcolor-diagnostics`, 59 `-fcrash-diagnostics-dir=../../tools/clang/crashreports`, 60 `-fprofile-use=prof.txt`, 61 `-Xclang`, 62 `-mllvm`, 63 `-Xclang`, 64 `-instcombine-lower-dbg-declare=0`, 65 `/Gy`, 66 `/FS`, 67 `/bigobj`, 68 `/utf-8`, 69 `/Zc:twoPhase`, 70 `/Zc:sizedDealloc-`, 71 `/X`, 72 `/D__WRL_ENABLE_FUNCTION_STATICS__`, 73 `-fmsc-version=1916`, 74 `/guard:cf,nochecks`, 75 `/Zc:dllexportInlines-`, 76 `-m64`, 77 `/Brepro`, 78 `-Wno-builtin-macro-redefined`, 79 `/W4`, 80 `/WX`, 81 `/wd4091`, 82 `/wd4127`, 83 `/Od`, 84 `/Ob0`, 85 `/GF`, 86 `/Z7`, 87 `/MDd`, 88 `/TP`, 89 `/wd4577`, 90 `/GR-`, 91 "@foo/args.rsp", 92 `-I../../buildtools/third_party/libc++/trunk/include`, 93 `/c`, 94 `/clang:-MD`, 95 `/clang:-MF`, `/clang:obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj.d`, 96 `../../base/third_party/double_conversion/double-conversion/fixed-dtoa.cc`, 97 `/Foobj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj`, 98 `/Fdobj/base/third_party/double_conversion/double_conversion_cc.pdb`, 99 }, 100 want: &flags.CommandFlags{ 101 ExecutablePath: "../../third_party/llvm-build/Release+Asserts/bin/clang-cl.exe", 102 TargetFilePaths: []string{ 103 "simple_input.txt", 104 "more_inputs.txt", 105 "../../base/third_party/double_conversion/double-conversion/fixed-dtoa.cc", 106 }, 107 IncludeDirPaths: []string{ 108 "../..", 109 "../../buildtools/third_party/libc++/trunk/include", 110 }, 111 WorkingDirectory: "out/Release", 112 EmittedDependencyFile: "obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj.d", 113 ExecRoot: er, 114 Dependencies: []string{ 115 "prof.txt", 116 "foo/args.rsp", 117 }, 118 Flags: []*flags.Flag{ 119 {Key: "-nologo"}, 120 {Key: "-showIncludes:user"}, 121 { 122 Key: "-imsvc", 123 Value: `..\..\third_party\depot_tools\win_toolchain\vs_files\a687d8e2e4114d9015eb550e1b156af21381faac\win_sdk\Include\10.0.19041.0\um`, 124 Joined: true, 125 }, 126 {Key: "-D", Value: `CR_CLANG_REVISION="n358615-fb1aa286-3"`, Joined: true}, 127 {Key: "-I", Value: "../..", Joined: true}, 128 {Key: "-fcolor-diagnostics"}, 129 {Key: "-fcrash-diagnostics-dir=", Value: "../../tools/clang/crashreports", Joined: true}, 130 {Key: "-fprofile-use=", Value: "prof.txt", Joined: true}, 131 {Key: "-Xclang", Value: "-mllvm"}, 132 {Key: "-Xclang", Value: "-instcombine-lower-dbg-declare=0"}, 133 {Key: "-Gy"}, 134 {Key: "-FS"}, 135 {Key: "-bigobj"}, 136 {Key: "-utf-8"}, 137 {Key: "-Zc:twoPhase"}, 138 {Key: "-Zc:sizedDealloc-"}, 139 {Key: "-X"}, 140 {Key: "-D", Value: "__WRL_ENABLE_FUNCTION_STATICS__", Joined: true}, 141 {Key: "-fmsc-version=", Value: "1916", Joined: true}, 142 {Key: "-guard:", Value: "cf,nochecks", Joined: true}, 143 {Key: "-Zc:dllexportInlines-"}, 144 {Key: "-m64"}, 145 {Key: "-Brepro"}, 146 {Key: "-W", Value: "no-builtin-macro-redefined", Joined: true}, 147 {Key: "-W4"}, 148 {Key: "-WX"}, 149 {Key: "-wd", Value: "4091", Joined: true}, 150 {Key: "-wd", Value: "4127", Joined: true}, 151 {Key: "-Od"}, 152 {Key: "-Ob0"}, 153 {Key: "-GF"}, 154 {Key: "-Z7"}, 155 {Key: "-MDd"}, 156 {Key: "-TP"}, 157 {Key: "-wd", Value: "4577", Joined: true}, 158 {Key: "-GR-"}, 159 {Value: "@foo/args.rsp"}, 160 {Key: "-I", Value: "../../buildtools/third_party/libc++/trunk/include", Joined: true}, 161 {Key: "-c"}, 162 {Key: "-clang:", Value: "-MD", Joined: true}, 163 {Key: "-Fd", Value: "obj/base/third_party/double_conversion/double_conversion_cc.pdb", Joined: true}, 164 }, 165 OutputFilePaths: []string{ 166 "obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj.d", 167 "obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj", 168 }, 169 }, 170 }, 171 { 172 name: "chromium clang-cl with dependency file defined by -MF in rsp file", 173 workingDir: "out/Release", 174 files: map[string][]byte{ 175 filepath.Join("out", "Release", "foo", "args.rsp"): []byte( 176 "/c\n" + 177 "simple_input.cc\nother_inputs.txt\n" + 178 // -MD tells the compiler to generate a dependency file and includes it in the compiled output with self-described dependencies, 179 // -MF tells the compiler the dependency file's name and filepath. 180 // Generally, there is only one -MF option in a single clang command. 181 "/clang:-MD\n" + 182 "/clang:-MF\n/clang:obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj.d\n" + 183 "../../base/third_party/double_conversion/double-conversion/fixed-dtoa.cc\n" + 184 "/Foobj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj\n" + 185 "/Fdobj/base/third_party/double_conversion/double_conversion_cc.pdb"), 186 filepath.Join("out", "Release", "simple_input.cc"): []byte("int main() {return 0;}"), 187 filepath.Join("out", "Release", "other_inputs.txt"): []byte("some another random text"), 188 }, 189 command: []string{ 190 "../../third_party/llvm-build/Release+Asserts/bin/clang-cl.exe", 191 "/nologo", 192 "/showIncludes:user", 193 `-imsvc..\..\third_party\depot_tools\win_toolchain\vs_files\a687d8e2e4114d9015eb550e1b156af21381faac\win_sdk\Include\10.0.19041.0\um`, 194 `-DCR_CLANG_REVISION="n358615-fb1aa286-3"`, 195 `-I../..`, 196 `-I../../buildtools/third_party/libc++/trunk/include`, 197 "@foo/args.rsp", 198 }, 199 want: &flags.CommandFlags{ 200 ExecutablePath: "../../third_party/llvm-build/Release+Asserts/bin/clang-cl.exe", 201 TargetFilePaths: []string{ 202 "simple_input.cc", 203 "other_inputs.txt", 204 "../../base/third_party/double_conversion/double-conversion/fixed-dtoa.cc", 205 }, 206 IncludeDirPaths: []string{ 207 "../..", 208 "../../buildtools/third_party/libc++/trunk/include", 209 }, 210 WorkingDirectory: "out/Release", 211 EmittedDependencyFile: "obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj.d", 212 ExecRoot: er, 213 Dependencies: []string{ 214 "foo/args.rsp", 215 }, 216 Flags: []*flags.Flag{ 217 {Key: "-nologo"}, 218 {Key: "-showIncludes:user"}, 219 { 220 Key: "-imsvc", 221 Value: `..\..\third_party\depot_tools\win_toolchain\vs_files\a687d8e2e4114d9015eb550e1b156af21381faac\win_sdk\Include\10.0.19041.0\um`, 222 Joined: true, 223 }, 224 {Key: "-D", Value: `CR_CLANG_REVISION="n358615-fb1aa286-3"`, Joined: true}, 225 {Key: "-I", Value: "../..", Joined: true}, 226 {Key: "-I", Value: "../../buildtools/third_party/libc++/trunk/include", Joined: true}, 227 {Value: "@foo/args.rsp"}, 228 }, 229 OutputFilePaths: []string{ 230 "obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj.d", 231 "obj/base/third_party/double_conversion/double_conversion/fixed-dtoa.obj", 232 }, 233 }, 234 }, 235 } 236 237 for _, test := range tests { 238 t.Run(test.name, func(t *testing.T) { 239 ctx := context.Background() 240 execroot.AddFilesWithContent(t, er, test.files) 241 got, err := parseFlags(ctx, test.command, test.workingDir, er) 242 if err != nil { 243 t.Errorf("parseFlags(%v,%v,%v).err = %v, want no error.", test.command, test.workingDir, er, err) 244 } 245 246 if diff := cmp.Diff(test.want, got, cmpopts.IgnoreUnexported(flags.Flag{})); diff != "" { 247 t.Errorf("Test %v, parseFlags(%v,%v,%v) \nreturned diff, (-want +got): %s", test.name, test.command, test.workingDir, er, diff) 248 } 249 }) 250 } 251 }