Merge "Add fuzzer for local prebuild graph runner" into rvc-qpr-dev
diff --git a/computepipe/runner/graph/LocalPrebuiltGraph.cpp b/computepipe/runner/graph/LocalPrebuiltGraph.cpp
index ae4cc8c..821e549 100644
--- a/computepipe/runner/graph/LocalPrebuiltGraph.cpp
+++ b/computepipe/runner/graph/LocalPrebuiltGraph.cpp
@@ -179,7 +179,7 @@
const std::string& prebuilt_library,
std::weak_ptr<PrebuiltEngineInterface> engineInterface) {
std::unique_lock<std::mutex> lock(LocalPrebuiltGraph::mCreationMutex);
- if (mPrebuiltGraphInstance != nullptr) {
+ if (mPrebuiltGraphInstance == nullptr) {
mPrebuiltGraphInstance = new LocalPrebuiltGraph();
}
if (mPrebuiltGraphInstance->mGraphState.load() != PrebuiltGraphState::UNINITIALIZED) {
diff --git a/computepipe/tests/fuzz/Android.bp b/computepipe/tests/fuzz/Android.bp
index 97f3435..6c54b64 100644
--- a/computepipe/tests/fuzz/Android.bp
+++ b/computepipe/tests/fuzz/Android.bp
@@ -80,3 +80,25 @@
"libprotobuf-mutator",
],
}
+
+cc_fuzz {
+ name: "local_prebuild_graph_fuzzer",
+ defaults: ["libcomputepipefuzz-defaults"],
+ cppflags:[
+ "-fexceptions",
+ "-Wno-unused-variable",
+ ],
+ static_libs: [
+ "computepipe_prebuilt_graph",
+ ],
+ shared_libs: [
+ "libstubgraphimpl",
+ ],
+ include_dirs: [
+ "packages/services/Car/computepipe",
+ "packages/services/Car/computepipe/runner/graph",
+ ],
+ srcs: [
+ "LocalPrebuildGraphFuzzer.cpp",
+ ],
+}
diff --git a/computepipe/tests/fuzz/Common.h b/computepipe/tests/fuzz/Common.h
new file mode 100644
index 0000000..ffaf015
--- /dev/null
+++ b/computepipe/tests/fuzz/Common.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CPP_COMPUTEPIPE_TESTS_FUZZ_COMMON_H_
+#define CPP_COMPUTEPIPE_TESTS_FUZZ_COMMON_H_
+
+namespace android {
+namespace automotive {
+namespace computepipe {
+namespace runner {
+namespace test {
+
+const int kMaxFuzzerConsumedBytes = 12;
+
+#define RUNNER_COMP_BASE_ENUM \
+ HANDLE_CONFIG_PHASE, /* verify handleConfigPhase */ \
+ HANDLE_EXECUTION_PHASE, /* verify handleExecutionPhase */ \
+ HANDLE_STOP_IMMEDIATE_PHASE, /* verify handleStopImmediatePhase */ \
+ HANDLE_STOP_WITH_FLUSH_PHASE, /* verify handleStopWithFlushPhase */ \
+ HANDLE_RESET_PHASE, /* verify handleResetPhase */ \
+ API_SUM
+
+} // namespace test
+} // namespace runner
+} // namespace computepipe
+} // namespace automotive
+} // namespace android
+
+#endif // CPP_COMPUTEPIPE_TESTS_FUZZ_COMMON_H_
diff --git a/computepipe/tests/fuzz/LocalPrebuildGraphFuzzer.cpp b/computepipe/tests/fuzz/LocalPrebuildGraphFuzzer.cpp
new file mode 100644
index 0000000..cd35918
--- /dev/null
+++ b/computepipe/tests/fuzz/LocalPrebuildGraphFuzzer.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <gmock/gmock.h>
+#include "ClientConfig.pb.h"
+#include "Common.h"
+#include "LocalPrebuiltGraph.h"
+#include "PrebuiltEngineInterface.h"
+
+using ::android::automotive::computepipe::runner::ClientConfig;
+
+namespace android {
+namespace automotive {
+namespace computepipe {
+namespace graph {
+
+namespace {
+
+enum LOCAL_PREBUILD_GRAPH_FUZZ_FUNCS {
+ GET_GRAPH_TYPE,
+ GET_GRAPH_STATE,
+ GET_STATUS,
+ GET_ERROR_MESSAGE,
+ GET_SUPPORTED_GRAPH_CONFIGS,
+ SET_INPUT_STREAM_DATA,
+ SET_INPUT_STREAM_PIXEL_DATA,
+ START_GRAPH_PROFILING,
+ STOP_GRAPH_PROFILING,
+ RUNNER_COMP_BASE_ENUM
+};
+
+// Barebones implementation of the PrebuiltEngineInterface. This implementation should suffice for
+// basic cases. More complicated use cases might need their own implementation of it.
+typedef std::function<void(int, int64_t, const runner::InputFrame&)> PixelCallback;
+typedef std::function<void(int, int64_t, std::string&&)> SerializedStreamCallback;
+typedef std::function<void(Status, std::string&&)> GraphTerminationCallback;
+class PrebuiltEngineInterfaceImpl : public PrebuiltEngineInterface {
+private:
+ PixelCallback mPixelCallbackFn;
+ SerializedStreamCallback mSerializedStreamCallbackFn;
+ GraphTerminationCallback mGraphTerminationCallbackFn;
+
+public:
+ virtual ~PrebuiltEngineInterfaceImpl() = default;
+
+ void DispatchPixelData(int streamId, int64_t timestamp,
+ const runner::InputFrame& frame) override {
+ mPixelCallbackFn(streamId, timestamp, frame);
+ }
+
+ void DispatchSerializedData(int streamId, int64_t timestamp, std::string&& data) override {
+ mSerializedStreamCallbackFn(streamId, timestamp, std::move(data));
+ }
+
+ void DispatchGraphTerminationMessage(Status status, std::string&& msg) override {
+ mGraphTerminationCallbackFn(status, std::move(msg));
+ }
+
+ void SetPixelCallback(PixelCallback callback) { mPixelCallbackFn = callback; }
+
+ void SetSerializedStreamCallback(SerializedStreamCallback callback) {
+ mSerializedStreamCallbackFn = callback;
+ }
+
+ void SetGraphTerminationCallback(GraphTerminationCallback callback) {
+ mGraphTerminationCallbackFn = callback;
+ }
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Initialization goes here
+ bool graphHasTerminated = false;
+ int numOutputStreamCallbacksReceived[4] = {0, 0, 0, 0};
+
+ PrebuiltEngineInterfaceImpl callback;
+ callback.SetGraphTerminationCallback(
+ [&graphHasTerminated](Status, std::string) { graphHasTerminated = true; });
+
+ // Add multiple pixel stream callback functions to see if all of them register.
+ callback.SetPixelCallback([&numOutputStreamCallbacksReceived](int streamIndex, int64_t,
+ const runner::InputFrame&) {
+ ASSERT_TRUE(streamIndex == 0 || streamIndex == 1);
+ numOutputStreamCallbacksReceived[streamIndex]++;
+ });
+
+ // Add multiple stream callback functions to see if all of them register.
+ callback.SetSerializedStreamCallback(
+ [&numOutputStreamCallbacksReceived](int streamIndex, int64_t, std::string&&) {
+ ASSERT_TRUE(streamIndex == 2 || streamIndex == 3);
+ numOutputStreamCallbacksReceived[streamIndex]++;
+ });
+
+ std::shared_ptr<PrebuiltEngineInterface> engineInterface =
+ std::static_pointer_cast<PrebuiltEngineInterface, PrebuiltEngineInterfaceImpl>(
+ std::make_shared<PrebuiltEngineInterfaceImpl>(callback));
+ PrebuiltGraph* graph = GetLocalGraphFromLibrary("libstubgraphimpl.so", engineInterface);
+
+ // Fuzz goes here
+ FuzzedDataProvider fdp(data, size);
+ while (fdp.remaining_bytes() > runner::test::kMaxFuzzerConsumedBytes) {
+ switch (fdp.ConsumeIntegralInRange<uint32_t>(0, API_SUM - 1)) {
+ case GET_GRAPH_TYPE: {
+ graph->GetGraphType();
+ break;
+ }
+ case GET_GRAPH_STATE: {
+ graph->GetGraphState();
+ break;
+ }
+ case GET_STATUS: {
+ graph->GetStatus();
+ break;
+ }
+ case GET_ERROR_MESSAGE: {
+ graph->GetErrorMessage();
+ break;
+ }
+ case GET_SUPPORTED_GRAPH_CONFIGS: {
+ graph->GetSupportedGraphConfigs();
+ break;
+ }
+ case SET_INPUT_STREAM_DATA: {
+ graph->SetInputStreamData(/*streamIndex =*/2, /* timestamp =*/0, /* data =*/"");
+ break;
+ }
+ case SET_INPUT_STREAM_PIXEL_DATA: {
+ runner::InputFrame inputFrame(0, 0, PixelFormat::RGB, 0, nullptr);
+ graph->SetInputStreamPixelData(/*streamIndex =*/1, /*timestamp =*/0,
+ /*inputFrame =*/inputFrame);
+ break;
+ }
+ case START_GRAPH_PROFILING: {
+ graph->StartGraphProfiling();
+ break;
+ }
+ case STOP_GRAPH_PROFILING: {
+ graph->StopGraphProfiling();
+ break;
+ }
+ case HANDLE_CONFIG_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleConfigPhase(e);
+ break;
+ }
+ case HANDLE_EXECUTION_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleExecutionPhase(e);
+ break;
+ }
+ case HANDLE_STOP_IMMEDIATE_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleStopImmediatePhase(e);
+ break;
+ }
+ case HANDLE_STOP_WITH_FLUSH_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleStopWithFlushPhase(e);
+ break;
+ }
+ case HANDLE_RESET_PHASE: {
+ std::map<int, int> maxOutputPacketsPerStream;
+ ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
+ e.setPhaseState(runner::PhaseState::ENTRY);
+ graph->handleResetPhase(e);
+ break;
+ }
+ default:
+ LOG(ERROR) << "Unexpected option aborting...";
+ break;
+ }
+ }
+ return 0;
+}
+
+} // namespace
+} // namespace graph
+} // namespace computepipe
+} // namespace automotive
+} // namespace android
diff --git a/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp b/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp
index 3e98e2a..44a0471 100644
--- a/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp
+++ b/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp
@@ -32,7 +32,7 @@
namespace stream_manager {
namespace {
-InputFrame convertToInputFrame(const fuzz::proto::Frame frame) {
+InputFrame convertToInputFrame(const fuzz::proto::Frame& frame) {
uint32_t height = frame.height();
uint32_t width = frame.width();
uint32_t stride = frame.stride();