fuzzing: Factor WireServer set up code out of frontend fuzzer

This will make it easier to bring up other Dawn backend fuzzers
that don't use the Null backend.

Bug: dawn:295
Change-Id: I176b937722a63509cab620ac2a90098d87a6049c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/14623
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/fuzzers/BUILD.gn b/src/fuzzers/BUILD.gn
index aea8fe6..2b51d6e 100644
--- a/src/fuzzers/BUILD.gn
+++ b/src/fuzzers/BUILD.gn
@@ -79,6 +79,20 @@
   ]
 }
 
+static_library("dawn_wire_server_fuzzer_common") {
+  sources = [
+    "DawnWireServerFuzzer.cpp",
+    "DawnWireServerFuzzer.h",
+  ]
+  public_deps = [
+    "${dawn_root}/:libdawn_native_static",
+    "${dawn_root}/:libdawn_wire_static",
+    "${dawn_root}/src/common",
+    "${dawn_root}/src/dawn:dawncpp",
+    "${dawn_root}/src/dawn:libdawn_proc",
+  ]
+}
+
 # TODO(rharrison): Remove asan_options once signal trap is no longer
 #                  needed.
 # Uses Dawn specific options and varies input data
@@ -123,7 +137,7 @@
     "DawnSPVCglslFastFuzzer.cpp",
   ]
   deps = [
-     "${dawn_shaderc_dir}:libshaderc_spvc",
+    "${dawn_shaderc_dir}:libshaderc_spvc",
   ]
 }
 
@@ -132,7 +146,7 @@
     "DawnSPVChlslFastFuzzer.cpp",
   ]
   deps = [
-     "${dawn_shaderc_dir}:libshaderc_spvc",
+    "${dawn_shaderc_dir}:libshaderc_spvc",
   ]
 }
 
@@ -141,7 +155,7 @@
     "DawnSPVCmslFastFuzzer.cpp",
   ]
   deps = [
-     "${dawn_shaderc_dir}:libshaderc_spvc",
+    "${dawn_shaderc_dir}:libshaderc_spvc",
   ]
 }
 
@@ -151,11 +165,7 @@
   ]
 
   deps = [
-    "${dawn_root}/:libdawn_native_static",
-    "${dawn_root}/:libdawn_wire_static",
-    "${dawn_root}/src/common",
-    "${dawn_root}/src/dawn:dawncpp",
-    "${dawn_root}/src/dawn:libdawn_proc",
+    ":dawn_wire_server_fuzzer_common",
   ]
 
   additional_configs = [ "${dawn_root}/src/common:dawn_internal" ]
diff --git a/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp b/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp
index ad904b7..7911738 100644
--- a/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp
+++ b/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp
@@ -12,85 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "DawnWireServerFuzzer.h"
+
 #include "common/Assert.h"
-#include "dawn/dawn_proc.h"
-#include "dawn/webgpu_cpp.h"
 #include "dawn_native/DawnNative.h"
-#include "dawn_wire/WireServer.h"
-
-#include <vector>
-
-class DevNull : public dawn_wire::CommandSerializer {
-  public:
-    void* GetCmdSpace(size_t size) override {
-        if (size > buf.size()) {
-            buf.resize(size);
-        }
-        return buf.data();
-    }
-    bool Flush() override {
-        return true;
-    }
-
-  private:
-    std::vector<char> buf;
-};
-
-static WGPUProcDeviceCreateSwapChain originalDeviceCreateSwapChain = nullptr;
-
-WGPUSwapChain ErrorDeviceCreateSwapChain(WGPUDevice device, const WGPUSwapChainDescriptor*) {
-    WGPUSwapChainDescriptor desc;
-    desc.nextInChain = nullptr;
-    desc.label = nullptr;
-    // A 0 implementation will trigger a swapchain creation error.
-    desc.implementation = 0;
-    return originalDeviceCreateSwapChain(device, &desc);
-}
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    DawnProcTable procs = dawn_native::GetProcs();
+    return DawnWireServerFuzzer::Run(data, size, [](dawn_native::Instance* instance) {
+        instance->DiscoverDefaultAdapters();
 
-    // Swapchains receive a pointer to an implementation. The fuzzer will pass garbage in so we
-    // intercept calls to create swapchains and make sure they always return error swapchains.
-    // This is ok for fuzzing because embedders of dawn_wire would always define their own
-    // swapchain handling.
-    originalDeviceCreateSwapChain = procs.deviceCreateSwapChain;
-    procs.deviceCreateSwapChain = ErrorDeviceCreateSwapChain;
+        std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
 
-    dawnProcSetProcs(&procs);
-
-    // Create an instance and find the null adapter to create a device with.
-    std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
-    instance->DiscoverDefaultAdapters();
-
-    std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
-
-    wgpu::Device nullDevice;
-    for (dawn_native::Adapter adapter : adapters) {
-        if (adapter.GetBackendType() == dawn_native::BackendType::Null) {
-            nullDevice = wgpu::Device::Acquire(adapter.CreateDevice());
-            break;
+        wgpu::Device nullDevice;
+        for (dawn_native::Adapter adapter : adapters) {
+            if (adapter.GetBackendType() == dawn_native::BackendType::Null) {
+                nullDevice = wgpu::Device::Acquire(adapter.CreateDevice());
+                break;
+            }
         }
-    }
-    ASSERT(nullDevice.Get() != nullptr);
 
-    DevNull devNull;
-    dawn_wire::WireServerDescriptor serverDesc = {};
-    serverDesc.device = nullDevice.Get();
-    serverDesc.procs = &procs;
-    serverDesc.serializer = &devNull;
-
-    std::unique_ptr<dawn_wire::WireServer> wireServer(new dawn_wire::WireServer(serverDesc));
-
-    wireServer->HandleCommands(reinterpret_cast<const char*>(data), size);
-
-    // Fake waiting for all previous commands before destroying the server.
-    nullDevice.Tick();
-
-    // Destroy the server before the device because it needs to free all objects.
-    wireServer = nullptr;
-    nullDevice = nullptr;
-    instance = nullptr;
-
-    return 0;
+        ASSERT(nullDevice.Get() != nullptr);
+        return nullDevice;
+    });
 }
diff --git a/src/fuzzers/DawnWireServerFuzzer.cpp b/src/fuzzers/DawnWireServerFuzzer.cpp
new file mode 100644
index 0000000..f7a19f1
--- /dev/null
+++ b/src/fuzzers/DawnWireServerFuzzer.cpp
@@ -0,0 +1,91 @@
+// Copyright 2019 The Dawn Authors
+//
+// 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 "DawnWireServerFuzzer.h"
+
+#include "common/Assert.h"
+#include "dawn/dawn_proc.h"
+#include "dawn/webgpu_cpp.h"
+#include "dawn_native/DawnNative.h"
+#include "dawn_wire/WireServer.h"
+
+#include <vector>
+
+namespace {
+
+    class DevNull : public dawn_wire::CommandSerializer {
+      public:
+        void* GetCmdSpace(size_t size) override {
+            if (size > buf.size()) {
+                buf.resize(size);
+            }
+            return buf.data();
+        }
+        bool Flush() override {
+            return true;
+        }
+
+      private:
+        std::vector<char> buf;
+    };
+
+    WGPUProcDeviceCreateSwapChain sOriginalDeviceCreateSwapChain = nullptr;
+
+    WGPUSwapChain ErrorDeviceCreateSwapChain(WGPUDevice device, const WGPUSwapChainDescriptor*) {
+        WGPUSwapChainDescriptor desc;
+        desc.nextInChain = nullptr;
+        desc.label = nullptr;
+        // A 0 implementation will trigger a swapchain creation error.
+        desc.implementation = 0;
+        return sOriginalDeviceCreateSwapChain(device, &desc);
+    }
+
+}  // namespace
+
+int DawnWireServerFuzzer::Run(const uint8_t* data, size_t size, MakeDeviceFn MakeDevice) {
+    DawnProcTable procs = dawn_native::GetProcs();
+
+    // Swapchains receive a pointer to an implementation. The fuzzer will pass garbage in so we
+    // intercept calls to create swapchains and make sure they always return error swapchains.
+    // This is ok for fuzzing because embedders of dawn_wire would always define their own
+    // swapchain handling.
+    sOriginalDeviceCreateSwapChain = procs.deviceCreateSwapChain;
+    procs.deviceCreateSwapChain = ErrorDeviceCreateSwapChain;
+
+    dawnProcSetProcs(&procs);
+
+    std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
+    wgpu::Device device = MakeDevice(instance.get());
+    ASSERT(device);
+
+    DevNull devNull;
+    dawn_wire::WireServerDescriptor serverDesc = {};
+    serverDesc.device = device.Get();
+    serverDesc.procs = &procs;
+    serverDesc.serializer = &devNull;
+
+    std::unique_ptr<dawn_wire::WireServer> wireServer(new dawn_wire::WireServer(serverDesc));
+
+    wireServer->HandleCommands(reinterpret_cast<const char*>(data), size);
+
+    // Fake waiting for all previous commands before destroying the server.
+    device.Tick();
+
+    // Destroy the server before the device because it needs to free all objects.
+    wireServer = nullptr;
+    device = nullptr;
+    instance = nullptr;
+
+    return 0;
+}
diff --git a/src/fuzzers/DawnWireServerFuzzer.h b/src/fuzzers/DawnWireServerFuzzer.h
new file mode 100644
index 0000000..b4c011e
--- /dev/null
+++ b/src/fuzzers/DawnWireServerFuzzer.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Dawn Authors
+//
+// 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 "dawn/webgpu_cpp.h"
+
+#include <cstdint>
+#include <functional>
+
+namespace dawn_native {
+
+    class Instance;
+
+}  // namespace dawn_native
+
+namespace DawnWireServerFuzzer {
+
+    using MakeDeviceFn = std::function<wgpu::Device(dawn_native::Instance*)>;
+
+    int Run(const uint8_t* data, size_t size, MakeDeviceFn MakeDevice);
+
+}  // namespace DawnWireServerFuzzer
diff --git a/src/fuzzers/StandaloneFuzzerMain.cpp b/src/fuzzers/StandaloneFuzzerMain.cpp
index ba8d94b..9755e1d 100644
--- a/src/fuzzers/StandaloneFuzzerMain.cpp
+++ b/src/fuzzers/StandaloneFuzzerMain.cpp
@@ -21,7 +21,7 @@
 
 int main(int argc, char** argv) {
     if (argc != 2) {
-        std::cout << "Usage: <standalone reproducer> [FILE]" << std::endl;
+        std::cout << "Usage: <standalone reproducer> FILE" << std::endl;
         return 1;
     }