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  }