Skip to content

Commit

Permalink
Suppress testing SemIR in int builtin tests.
Browse files Browse the repository at this point in the history
Add `EXTRA-ARGS:` support to file_test, to add arguments without
overriding the default arguments. Use `EXTRA-ARGS: --no-dump-sem-ir` to
turn off SemIR dumping and thus SemIR testing in the int builtin tests,
which validate correct behavior through diagnostics instead.

This doesn't get us any closer to supporting more targeted SemIR dumping
/ testing, but hopefully this is a generally useful feature for argument
testing.

Requested in review of carbon-language#4716.
  • Loading branch information
zygoloid committed Dec 30, 2024
1 parent 89df777 commit 3ec37ac
Show file tree
Hide file tree
Showing 31 changed files with 57 additions and 11,668 deletions.
9 changes: 9 additions & 0 deletions testing/file_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ Supported comment markers are:
ARGS can be specified at most once. If not provided, the FileTestBase child
is responsible for providing default arguments.
- ```
// EXTRA-ARGS: <arguments>
```
`EXTRA-ARGS` specifies additional arguments that are appended after the
default argument list. It has the same substitution behavior as `ARGS`.
`EXTRA-ARGS` can be specified at most once, and a test cannot specify both
`ARGS` and `EXTRA-ARGS`.
- ```
// SET-CAPTURE-CONSOLE-OUTPUT
```
Expand Down
23 changes: 16 additions & 7 deletions testing/file_test/file_test_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ auto FileTestBase::ProcessTestFileAndRun(TestContext& context)
// Process arguments.
if (context.test_args.empty()) {
context.test_args = GetDefaultArgs();
context.test_args.append(context.extra_args);
}
CARBON_RETURN_IF_ERROR(
DoArgReplacements(context.test_args, context.test_files));
Expand Down Expand Up @@ -767,24 +768,31 @@ static auto TryConsumeCheck(
return true;
}

// Processes ARGS lines when found. Returns true if the line is consumed.
// Processes ARGS and EXTRA-ARGS lines when found. Returns true if the line is
// consumed.
static auto TryConsumeArgs(llvm::StringRef line, llvm::StringRef line_trimmed,
llvm::SmallVector<std::string>* args)
llvm::SmallVector<std::string>* args,
llvm::SmallVector<std::string>* extra_args)
-> ErrorOr<bool> {
if (!line_trimmed.consume_front("// ARGS: ")) {
llvm::SmallVector<std::string>* arg_list = nullptr;
if (line_trimmed.consume_front("// ARGS: ")) {
arg_list = args;
} else if (line_trimmed.consume_front("// EXTRA-ARGS: ")) {
arg_list = extra_args;
} else {
return false;
}

if (!args->empty()) {
return ErrorBuilder() << "ARGS was specified multiple times: "
if (!args->empty() || !extra_args->empty()) {
return ErrorBuilder() << "ARGS / EXTRA-ARGS specified multiple times: "
<< line.str();
}

// Split the line into arguments.
std::pair<llvm::StringRef, llvm::StringRef> cursor =
llvm::getToken(line_trimmed);
while (!cursor.first.empty()) {
args->push_back(std::string(cursor.first));
arg_list->push_back(std::string(cursor.first));
cursor = llvm::getToken(cursor.second);
}

Expand Down Expand Up @@ -884,7 +892,8 @@ auto FileTestBase::ProcessTestFile(TestContext& context) -> ErrorOr<Success> {
FileTestLine(split.file_index, line_index, line));

CARBON_ASSIGN_OR_RETURN(
is_consumed, TryConsumeArgs(line, line_trimmed, &context.test_args));
is_consumed, TryConsumeArgs(line, line_trimmed, &context.test_args,
&context.extra_args));
if (is_consumed) {
continue;
}
Expand Down
4 changes: 4 additions & 0 deletions testing/file_test/file_test_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ class FileTestBase : public testing::Test {
// Arguments for the test, generated from ARGS.
llvm::SmallVector<std::string> test_args;

// Extra arguments for the test, generated from EXTRA-ARGS. Unlike ARGS,
// setting EXTRA-ARGS does not suppress the default arguments.
llvm::SmallVector<std::string> extra_args;

// Files in the test, generated by content and splits.
llvm::SmallVector<TestFile> test_files;

Expand Down
108 changes: 1 addition & 107 deletions toolchain/check/testdata/builtins/int/and.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/and.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/and.carbon
// EXTRA-ARGS: --no-dump-sem-ir

// --- int_and.carbon

Expand All @@ -19,110 +20,3 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
return And(a, b);
}

// CHECK:STDOUT: --- int_and.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [template]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [template]
// CHECK:STDOUT: %And.type: type = fn_type @And [template]
// CHECK:STDOUT: %And: %And.type = struct_value () [template]
// CHECK:STDOUT: %int_8.2: Core.IntLiteral = int_value 8 [template]
// CHECK:STDOUT: %array_type: type = array_type %int_8.2, %i32 [template]
// CHECK:STDOUT: %ptr: type = ptr_type %array_type [template]
// CHECK:STDOUT: %RuntimeCall.type: type = fn_type @RuntimeCall [template]
// CHECK:STDOUT: %RuntimeCall: %RuntimeCall.type = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .Int = %import_ref.1
// CHECK:STDOUT: .ImplicitAs = %import_ref.5
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .And = %And.decl
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .arr_p = @__global_init.%arr_p
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %And.decl: %And.type = fn_decl @And [template = constants.%And] {
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
// CHECK:STDOUT: %b.patt: %i32 = binding_pattern b
// CHECK:STDOUT: %b.param_patt: %i32 = value_param_pattern %b.patt, runtime_param1
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param2
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc2_27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
// CHECK:STDOUT: %.loc2_11: type = splice_block %i32.loc2_11 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc2_11: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_11: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
// CHECK:STDOUT: %b.param: %i32 = value_param runtime_param1
// CHECK:STDOUT: %.loc2_19: type = splice_block %i32.loc2_19 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc2_19: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_19: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %b: %i32 = bind_name b, %b.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param2
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %arr.var: ref %array_type = var arr
// CHECK:STDOUT: %arr: ref %array_type = bind_name arr, %arr.var
// CHECK:STDOUT: %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
// CHECK:STDOUT: %b.patt: %i32 = binding_pattern b
// CHECK:STDOUT: %b.param_patt: %i32 = value_param_pattern %b.patt, runtime_param1
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param2
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc7_35: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc7_35: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
// CHECK:STDOUT: %.loc7_19: type = splice_block %i32.loc7_19 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc7_19: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc7_19: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
// CHECK:STDOUT: %b.param: %i32 = value_param runtime_param1
// CHECK:STDOUT: %.loc7_27: type = splice_block %i32.loc7_27 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc7_27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc7_27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %b: %i32 = bind_name b, %b.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param2
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @And(%a.param_patt: %i32, %b.param_patt: %i32) -> %i32 = "int.and";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a.param_patt: %i32, %b.param_patt: %i32) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %And.ref: %And.type = name_ref And, file.%And.decl [template = constants.%And]
// CHECK:STDOUT: %a.ref: %i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: %i32 = name_ref b, %b
// CHECK:STDOUT: %int.and: init %i32 = call %And.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc8_19.1: %i32 = value_of_initializer %int.and
// CHECK:STDOUT: %.loc8_19.2: %i32 = converted %int.and, %.loc8_19.1
// CHECK:STDOUT: return %.loc8_19.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %arr.ref: ref %array_type = name_ref arr, file.%arr
// CHECK:STDOUT: %addr: %ptr = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: %ptr = bind_name arr_p, %addr
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
121 changes: 1 addition & 120 deletions toolchain/check/testdata/builtins/int/complement.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/complement.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/complement.carbon
// EXTRA-ARGS: --no-dump-sem-ir

// --- int_complement.carbon

Expand All @@ -20,123 +21,3 @@ fn RuntimeCall(a: i32) -> i32 {
return Complement(a);
}

// CHECK:STDOUT: --- int_complement.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [template]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [template]
// CHECK:STDOUT: %Complement.type: type = fn_type @Complement [template]
// CHECK:STDOUT: %Complement: %Complement.type = struct_value () [template]
// CHECK:STDOUT: %And.type: type = fn_type @And [template]
// CHECK:STDOUT: %And: %And.type = struct_value () [template]
// CHECK:STDOUT: %int_15584169.2: Core.IntLiteral = int_value 15584169 [template]
// CHECK:STDOUT: %array_type: type = array_type %int_15584169.2, %i32 [template]
// CHECK:STDOUT: %ptr: type = ptr_type %array_type [template]
// CHECK:STDOUT: %RuntimeCall.type: type = fn_type @RuntimeCall [template]
// CHECK:STDOUT: %RuntimeCall: %RuntimeCall.type = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .Int = %import_ref.1
// CHECK:STDOUT: .ImplicitAs = %import_ref.5
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Complement = %Complement.decl
// CHECK:STDOUT: .And = %And.decl
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .arr_p = @__global_init.%arr_p
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Complement.decl: %Complement.type = fn_decl @Complement [template = constants.%Complement] {
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param1
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc2_26: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_26: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
// CHECK:STDOUT: %.loc2: type = splice_block %i32.loc2_18 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc2_18: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc2_18: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %And.decl: %And.type = fn_decl @And [template = constants.%And] {
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
// CHECK:STDOUT: %b.patt: %i32 = binding_pattern b
// CHECK:STDOUT: %b.param_patt: %i32 = value_param_pattern %b.patt, runtime_param1
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param2
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc3_27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc3_27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
// CHECK:STDOUT: %.loc3_11: type = splice_block %i32.loc3_11 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc3_11: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc3_11: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
// CHECK:STDOUT: %b.param: %i32 = value_param runtime_param1
// CHECK:STDOUT: %.loc3_19: type = splice_block %i32.loc3_19 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc3_19: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc3_19: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %b: %i32 = bind_name b, %b.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param2
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %arr.var: ref %array_type = var arr
// CHECK:STDOUT: %arr: ref %array_type = bind_name arr, %arr.var
// CHECK:STDOUT: %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param1
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc8_27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc8_27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
// CHECK:STDOUT: %.loc8: type = splice_block %i32.loc8_19 [template = constants.%i32] {
// CHECK:STDOUT: %int_32.loc8_19: Core.IntLiteral = int_value 32 [template = constants.%int_32]
// CHECK:STDOUT: %i32.loc8_19: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param1
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Complement(%a.param_patt: %i32) -> %i32 = "int.complement";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @And(%a.param_patt: %i32, %b.param_patt: %i32) -> %i32 = "int.and";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a.param_patt: %i32) -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Complement.ref: %Complement.type = name_ref Complement, file.%Complement.decl [template = constants.%Complement]
// CHECK:STDOUT: %a.ref: %i32 = name_ref a, %a
// CHECK:STDOUT: %int.complement: init %i32 = call %Complement.ref(%a.ref)
// CHECK:STDOUT: %.loc9_23.1: %i32 = value_of_initializer %int.complement
// CHECK:STDOUT: %.loc9_23.2: %i32 = converted %int.complement, %.loc9_23.1
// CHECK:STDOUT: return %.loc9_23.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %arr.ref: ref %array_type = name_ref arr, file.%arr
// CHECK:STDOUT: %addr: %ptr = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: %ptr = bind_name arr_p, %addr
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
Loading

0 comments on commit 3ec37ac

Please sign in to comment.