Skip to content

Commit e58ce3e

Browse files
authored
Add coverage testing for parse node kinds. (#4436)
This refactors the diagnostic kind coverage check into something that also works for node kinds. Then, since this points out a few node kinds that aren't having their parse verified, I'm adding minor tests for those.
1 parent 03ddeb5 commit e58ce3e

File tree

8 files changed

+259
-145
lines changed

8 files changed

+259
-145
lines changed

toolchain/diagnostics/BUILD

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,20 @@ manifest(
6464
)
6565

6666
cc_test(
67-
name = "emitted_diagnostics_test",
67+
name = "coverage_test",
6868
size = "small",
69-
srcs = ["emitted_diagnostics_test.cpp"],
69+
srcs = ["coverage_test.cpp"],
7070
args = ["--testdata_manifest=$(location :all_testdata.txt)"],
7171
data = [
7272
":all_testdata.txt",
7373
"//toolchain/testing:all_testdata",
7474
],
7575
deps = [
7676
":diagnostic_kind",
77-
"//common:set",
7877
"//testing/base:gtest_main",
78+
"//toolchain/testing:coverage_helper",
7979
"@abseil-cpp//absl/flags:flag",
8080
"@googletest//:gtest",
81-
"@llvm-project//llvm:Support",
82-
"@re2",
8381
],
8482
)
8583

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
2+
// Exceptions. See /LICENSE for license information.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
#include <gtest/gtest.h>
6+
7+
#include "absl/flags/flag.h"
8+
#include "toolchain/diagnostics/diagnostic_kind.h"
9+
#include "toolchain/testing/coverage_helper.h"
10+
11+
ABSL_FLAG(std::string, testdata_manifest, "",
12+
"A path to a file containing repo-relative names of test files.");
13+
14+
namespace Carbon {
15+
namespace {
16+
17+
constexpr DiagnosticKind DiagnosticKinds[] = {
18+
#define CARBON_DIAGNOSTIC_KIND(Name) DiagnosticKind::Name,
19+
#include "toolchain/diagnostics/diagnostic_kind.def"
20+
};
21+
22+
constexpr DiagnosticKind UntestedDiagnosticKinds[] = {
23+
// These exist only for unit tests.
24+
DiagnosticKind::TestDiagnostic,
25+
DiagnosticKind::TestDiagnosticNote,
26+
27+
// These diagnose filesystem issues that are hard to unit test.
28+
DiagnosticKind::ErrorReadingFile,
29+
DiagnosticKind::ErrorStattingFile,
30+
DiagnosticKind::FileTooLarge,
31+
32+
// Int literals are currently limited to i32. Once that's fixed, this
33+
// should be tested.
34+
DiagnosticKind::ArrayBoundTooLarge,
35+
36+
// This isn't feasible to test with a normal testcase, but is tested in
37+
// lex/tokenized_buffer_test.cpp.
38+
DiagnosticKind::TooManyTokens,
39+
40+
// TODO: Should look closer at these, but adding tests is a high risk of
41+
// loss in merge conflicts due to the amount of tests being changed right
42+
// now.
43+
DiagnosticKind::ExternLibraryInImporter,
44+
DiagnosticKind::ExternLibraryOnDefinition,
45+
DiagnosticKind::HexadecimalEscapeMissingDigits,
46+
DiagnosticKind::ImplOfUndefinedInterface,
47+
DiagnosticKind::IncompleteTypeInFunctionParam,
48+
DiagnosticKind::InvalidDigit,
49+
DiagnosticKind::InvalidDigitSeparator,
50+
DiagnosticKind::InvalidHorizontalWhitespaceInString,
51+
DiagnosticKind::MismatchedIndentInString,
52+
DiagnosticKind::ModifierPrivateNotAllowed,
53+
DiagnosticKind::MultiLineStringWithDoubleQuotes,
54+
DiagnosticKind::NameAmbiguousDueToExtend,
55+
DiagnosticKind::TooManyDigits,
56+
DiagnosticKind::UnaryOperatorRequiresWhitespace,
57+
DiagnosticKind::UnicodeEscapeSurrogate,
58+
DiagnosticKind::UnicodeEscapeTooLarge,
59+
DiagnosticKind::UnknownBaseSpecifier,
60+
DiagnosticKind::UnsupportedCRLineEnding,
61+
DiagnosticKind::UnsupportedLFCRLineEnding,
62+
};
63+
64+
// Looks for diagnostic kinds that aren't covered by a file_test.
65+
TEST(Coverage, DiagnosticKind) {
66+
Testing::TestKindCoverage(absl::GetFlag(FLAGS_testdata_manifest),
67+
R"(^ *// CHECK:STDERR: .*\.carbon:.* \[(\w+)\]$)",
68+
llvm::ArrayRef(DiagnosticKinds),
69+
llvm::ArrayRef(UntestedDiagnosticKinds));
70+
}
71+
72+
} // namespace
73+
} // namespace Carbon

toolchain/diagnostics/emitted_diagnostics_test.cpp

Lines changed: 0 additions & 130 deletions
This file was deleted.

toolchain/parse/BUILD

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

55
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
6+
load("//bazel/manifest:defs.bzl", "manifest")
67
load("//testing/fuzzing:rules.bzl", "cc_fuzz_test")
78

89
package(default_visibility = ["//visibility:public"])
@@ -12,6 +13,11 @@ filegroup(
1213
data = glob(["testdata/**/*.carbon"]),
1314
)
1415

16+
manifest(
17+
name = "testdata.txt",
18+
srcs = [":testdata"],
19+
)
20+
1521
cc_library(
1622
name = "node_kind",
1723
srcs = ["node_kind.cpp"],
@@ -198,3 +204,21 @@ cc_test(
198204
"@googletest//:gtest",
199205
],
200206
)
207+
208+
cc_test(
209+
name = "coverage_test",
210+
size = "small",
211+
srcs = ["coverage_test.cpp"],
212+
args = ["--testdata_manifest=$(location :testdata.txt)"],
213+
data = [
214+
":testdata",
215+
":testdata.txt",
216+
],
217+
deps = [
218+
":node_kind",
219+
"//testing/base:gtest_main",
220+
"//toolchain/testing:coverage_helper",
221+
"@abseil-cpp//absl/flags:flag",
222+
"@googletest//:gtest",
223+
],
224+
)

toolchain/parse/coverage_test.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
2+
// Exceptions. See /LICENSE for license information.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
#include <gtest/gtest.h>
6+
7+
#include "absl/flags/flag.h"
8+
#include "toolchain/parse/node_kind.h"
9+
#include "toolchain/testing/coverage_helper.h"
10+
11+
ABSL_FLAG(std::string, testdata_manifest, "",
12+
"A path to a file containing repo-relative names of test files.");
13+
14+
namespace Carbon::Parse {
15+
namespace {
16+
17+
constexpr NodeKind NodeKinds[] = {
18+
#define CARBON_PARSE_NODE_KIND(Name) NodeKind::Name,
19+
#include "toolchain/parse/node_kind.def"
20+
};
21+
22+
constexpr NodeKind UntestedNodeKinds[] = {NodeKind::Placeholder};
23+
24+
// Looks for node kinds that aren't covered by a file_test.
25+
TEST(Coverage, NodeKind) {
26+
Testing::TestKindCoverage(absl::GetFlag(FLAGS_testdata_manifest),
27+
R"(kind: '(\w+)')", llvm::ArrayRef(NodeKinds),
28+
llvm::ArrayRef(UntestedNodeKinds));
29+
}
30+
31+
} // namespace
32+
} // namespace Carbon::Parse

toolchain/parse/testdata/operators/infix.carbon

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,42 @@
88
// TIP: To dump output, run:
99
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/infix.carbon
1010

11-
var n: i8 = n * n;
11+
fn F() {
12+
n * n;
13+
n ^ n;
14+
n >= n;
15+
n >> n;
16+
n / n;
17+
}
1218

1319
// CHECK:STDOUT: - filename: infix.carbon
1420
// CHECK:STDOUT: parse_tree: [
1521
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
16-
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
17-
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'n'},
18-
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i8'},
19-
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
20-
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
21-
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
22-
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
23-
// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 3},
24-
// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 9},
22+
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
23+
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'F'},
24+
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
25+
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
26+
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
27+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
28+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
29+
// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 3},
30+
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 4},
31+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
32+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
33+
// CHECK:STDOUT: {kind: 'InfixOperatorCaret', text: '^', subtree_size: 3},
34+
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 4},
35+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
36+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
37+
// CHECK:STDOUT: {kind: 'InfixOperatorGreaterEqual', text: '>=', subtree_size: 3},
38+
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 4},
39+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
40+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
41+
// CHECK:STDOUT: {kind: 'InfixOperatorGreaterGreater', text: '>>', subtree_size: 3},
42+
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 4},
43+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
44+
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
45+
// CHECK:STDOUT: {kind: 'InfixOperatorSlash', text: '/', subtree_size: 3},
46+
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 4},
47+
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 26},
2548
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
2649
// CHECK:STDOUT: ]

toolchain/testing/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ cc_library(
3737
],
3838
)
3939

40+
cc_library(
41+
name = "coverage_helper",
42+
testonly = 1,
43+
hdrs = ["coverage_helper.h"],
44+
deps = [
45+
"//common:set",
46+
"@googletest//:gtest",
47+
"@llvm-project//llvm:Support",
48+
"@re2",
49+
],
50+
)
51+
4052
file_test(
4153
name = "file_test",
4254
size = "small",

0 commit comments

Comments
 (0)