Просмотр исходного кода

Split executable semantics fuzzer into cc_binary and cc_test

This is a workaround for #1208, allowing to remove manual tag to allow building and testing fuzzer code during precommits and in bazel test ...

Tested:
bazel test -k ...
bazel build -c opt executable_semantics/fuzzing:executable_semantics_fuzzer
bazel-bin/executable_semantics/fuzzing/executable_semantics_fuzzer
pk19604014 4 лет назад
Родитель
Сommit
0b4e9b5ecb

+ 0 - 0
crash-da39a3ee5e6b4b0d3255bfef95601890afd80709


+ 29 - 10
executable_semantics/fuzzing/BUILD

@@ -27,6 +27,10 @@ cc_library(
         "//common:check",
         "//common/fuzzing:carbon_cc_proto",
         "//common/fuzzing:proto_to_carbon_lib",
+        "//executable_semantics/interpreter:exec_program",
+        "//executable_semantics/syntax",
+        "//executable_semantics/syntax:prelude",
+        "@com_google_protobuf//:protobuf_headers",
         "@llvm-project//llvm:Support",
     ],
 )
@@ -69,6 +73,27 @@ cc_binary(
     ],
 )
 
+filegroup(
+    name = "fuzzer_corpus_files",
+    srcs = glob(["fuzzer_corpus/**"]),
+)
+
+cc_test(
+    name = "fuzzer_util_test",
+    srcs = ["fuzzer_util_test.cpp"],
+    args = [
+        "$(locations fuzzer_corpus_files)",
+    ],
+    data = [
+        ":fuzzer_corpus_files",
+    ],
+    deps = [
+        ":fuzzer_util",
+        "@com_google_googletest//:gtest",
+        "@llvm-project//llvm:Support",
+    ],
+)
+
 cc_test(
     name = "proto_to_carbon_test",
     srcs = ["proto_to_carbon_test.cpp"],
@@ -91,21 +116,15 @@ cc_test(
     ],
 )
 
-# Needs `--config=proto-fuzzer` for `bazel build` / `bazel test`.
-cc_fuzz_test(
+# Needs `--config=proto-fuzzer` for `bazel build`.
+cc_binary(
     name = "executable_semantics_fuzzer",
-    size = "small",
+    testonly = 1,
     srcs = ["executable_semantics_fuzzer.cpp"],
-    corpus = glob(["fuzzer_corpus/**"]),
-    tags = ["manual"],
+    features = ["fuzzer"],
     deps = [
         ":fuzzer_util",
-        "//common/fuzzing:carbon_cc_proto",
-        "//executable_semantics/interpreter:exec_program",
-        "//executable_semantics/syntax",
-        "//executable_semantics/syntax:prelude",
         "@com_google_libprotobuf_mutator//:libprotobuf_mutator",
-        "@com_google_protobuf//:protobuf_headers",
         "@llvm-project//llvm:Support",
     ],
 )

+ 0 - 32
executable_semantics/fuzzing/executable_semantics_fuzzer.cpp

@@ -2,41 +2,9 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#include <google/protobuf/text_format.h>
 #include <libprotobuf_mutator/src/libfuzzer/libfuzzer_macro.h>
 
-#include "common/fuzzing/carbon.pb.h"
 #include "executable_semantics/fuzzing/fuzzer_util.h"
-#include "executable_semantics/interpreter/exec_program.h"
-#include "executable_semantics/syntax/parse.h"
-#include "executable_semantics/syntax/prelude.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace Carbon {
-
-// Parses and executes a fuzzer-generated program.
-void ParseAndExecute(const Fuzzing::CompilationUnit& compilation_unit) {
-  const std::string source = ProtoToCarbonWithMain(compilation_unit);
-
-  Arena arena;
-  ErrorOr<AST> ast = ParseFromString(&arena, "Fuzzer.carbon", source,
-                                     /*parser_debug=*/false);
-  if (!ast.ok()) {
-    llvm::errs() << "Parsing failed: " << ast.error().message() << "\n";
-    return;
-  }
-  AddPrelude("executable_semantics/data/prelude.carbon", &arena,
-             &ast->declarations);
-  const ErrorOr<int> result =
-      ExecProgram(&arena, *ast, /*trace_stream=*/std::nullopt);
-  if (!result.ok()) {
-    llvm::errs() << "Execution failed: " << result.error().message() << "\n";
-    return;
-  }
-  llvm::outs() << "Executed OK: " << *result << "\n";
-}
-
-}  // namespace Carbon
 
 DEFINE_TEXT_PROTO_FUZZER(const Carbon::Fuzzing::Carbon& input) {
   Carbon::ParseAndExecute(input.compilation_unit());

+ 25 - 0
executable_semantics/fuzzing/fuzzer_util.cpp

@@ -6,6 +6,10 @@
 
 #include "common/check.h"
 #include "common/fuzzing/proto_to_carbon.h"
+#include "executable_semantics/interpreter/exec_program.h"
+#include "executable_semantics/syntax/parse.h"
+#include "executable_semantics/syntax/prelude.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace Carbon {
 
@@ -29,4 +33,25 @@ auto ProtoToCarbonWithMain(const Fuzzing::CompilationUnit& compilation_unit)
   return Carbon::ProtoToCarbon(compilation_unit) + (has_main ? "" : EmptyMain);
 }
 
+void ParseAndExecute(const Fuzzing::CompilationUnit& compilation_unit) {
+  const std::string source = ProtoToCarbonWithMain(compilation_unit);
+
+  Arena arena;
+  ErrorOr<AST> ast = ParseFromString(&arena, "Fuzzer.carbon", source,
+                                     /*parser_debug=*/false);
+  if (!ast.ok()) {
+    llvm::errs() << "Parsing failed: " << ast.error().message() << "\n";
+    return;
+  }
+  AddPrelude("executable_semantics/data/prelude.carbon", &arena,
+             &ast->declarations);
+  const ErrorOr<int> result =
+      ExecProgram(&arena, *ast, /*trace_stream=*/std::nullopt);
+  if (!result.ok()) {
+    llvm::errs() << "Execution failed: " << result.error().message() << "\n";
+    return;
+  }
+  llvm::outs() << "Executed OK: " << *result << "\n";
+}
+
 }  // namespace Carbon

+ 3 - 0
executable_semantics/fuzzing/fuzzer_util.h

@@ -14,6 +14,9 @@ namespace Carbon {
 auto ProtoToCarbonWithMain(const Fuzzing::CompilationUnit& compilation_unit)
     -> std::string;
 
+// Parses and executes a fuzzer-generated program.
+void ParseAndExecute(const Fuzzing::CompilationUnit& compilation_unit);
+
 }  // namespace Carbon
 
 #endif  // EXECUTABLE_SEMANTICS_FUZZING_FUZZER_UTIL_H_

+ 47 - 0
executable_semantics/fuzzing/fuzzer_util_test.cpp

@@ -0,0 +1,47 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include "executable_semantics/fuzzing/fuzzer_util.h"
+
+#include <gmock/gmock.h>
+#include <google/protobuf/text_format.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace Carbon::Testing {
+namespace {
+
+static std::vector<llvm::StringRef>* carbon_files = nullptr;
+
+// A workaround for https://github.com/carbon-language/carbon-lang/issues/1208.
+TEST(FuzzerUtilTest, RunFuzzerOnCorpus) {
+  int file_count = 0;
+  for (const llvm::StringRef f : *carbon_files) {
+    llvm::outs() << "Processing " << f << "\n";
+    std::ifstream file(f.str(), std::ios::in);
+    ASSERT_TRUE(file.is_open());
+    std::stringstream contents;
+    contents << file.rdbuf();
+    Fuzzing::Carbon carbon_proto;
+    ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(contents.str(),
+                                                              &carbon_proto));
+    ParseAndExecute(carbon_proto.compilation_unit());
+    ++file_count;
+  }
+  EXPECT_GT(file_count, 0);
+}
+
+}  // namespace
+}  // namespace Carbon::Testing
+
+auto main(int argc, char** argv) -> int {
+  ::testing::InitGoogleTest(&argc, argv);
+  Carbon::Testing::carbon_files =
+      new std::vector<llvm::StringRef>(&argv[1], &argv[argc]);
+  return RUN_ALL_TESTS();
+}