// Copyright 2025 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// One-off "spot"/regression/smoke tests for Emdawnwebgpu.

#include <dawn/webgpu_cpp_print.h>
#include <emscripten.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <webgpu/webgpu_cpp.h>

#include <array>
#include <string>
#include <utility>

#include "src/dawn/utils/WGPUHelpers.h"

namespace {

namespace utils = dawn::utils;
using testing::_;
using testing::HasSubstr;

enum class Mode {
    // Request Compat, and don't request any features/limits
    MinCompat,
    // Request Core, and request all features/limits
    MaxCore,
};

std::ostream& operator<<(std::ostream& os, const Mode& mode) {
    switch (mode) {
        case Mode::MinCompat:
            return os << "MinCompat";
        case Mode::MaxCore:
            return os << "MaxCore";
    }
}

class SpotTests : public ::testing::TestWithParam<Mode> {
  public:
    void SetUp() override {
        static constexpr auto kInstanceFeatures =
            std::array{wgpu::InstanceFeatureName::TimedWaitAny};
        wgpu::InstanceDescriptor instanceDesc{.requiredFeatureCount = kInstanceFeatures.size(),
                                              .requiredFeatures = kInstanceFeatures.data()};
        mInstance = wgpu::CreateInstance(&instanceDesc);

        wgpu::Adapter adapter;

        wgpu::RequestAdapterOptions options = {};
        switch (GetParam()) {
            case Mode::MinCompat:
                options.featureLevel = wgpu::FeatureLevel::Compatibility;
                break;
            case Mode::MaxCore:
                options.featureLevel = wgpu::FeatureLevel::Core;
                break;
        }
        EXPECT_EQ(wgpu::WaitStatus::Success,
                  mInstance.WaitAny(mInstance.RequestAdapter(
                                        &options, wgpu::CallbackMode::WaitAnyOnly,
                                        [&adapter](wgpu::RequestAdapterStatus, wgpu::Adapter a,
                                                   wgpu::StringView) { adapter = std::move(a); }),
                                    UINT64_MAX));
        EXPECT_TRUE(adapter);
        // Get adapter features
        wgpu::SupportedFeatures features;
        adapter.GetFeatures(&features);
        // Get adapter limits
        wgpu::Limits limits;
        wgpu::CompatibilityModeLimits compatLimits;
        limits.nextInChain = &compatLimits;
        adapter.GetLimits(&limits);

        wgpu::DeviceDescriptor deviceDesc;
        switch (GetParam()) {
            case Mode::MinCompat:
                // Request no limits and features
                deviceDesc.requiredLimits = nullptr;
                deviceDesc.requiredFeatureCount = 0;
                deviceDesc.requiredFeatures = nullptr;
                break;
            case Mode::MaxCore:
                // Request max limits and features
                deviceDesc.requiredLimits = &limits;
                deviceDesc.requiredFeatureCount = features.featureCount;
                deviceDesc.requiredFeatures = features.features;
                break;
        }

        wgpu::Device device;
        EXPECT_EQ(wgpu::WaitStatus::Success,
                  mInstance.WaitAny(
                      adapter.RequestDevice(&deviceDesc, wgpu::CallbackMode::WaitAnyOnly,
                                            [&device](wgpu::RequestDeviceStatus, wgpu::Device d,
                                                      wgpu::StringView) { device = std::move(d); }),
                      UINT64_MAX));
        EXPECT_TRUE(device);

        // Check what we actually got.
        wgpu::SupportedFeatures deviceFeatures;
        device.GetFeatures(&deviceFeatures);
        mGotCompatibilityMode = true;
        for (auto feature :
             DAWN_UNSAFE_TODO(std::span(deviceFeatures.features, deviceFeatures.featureCount))) {
            if (feature == wgpu::FeatureName::CoreFeaturesAndLimits) {
                mGotCompatibilityMode = false;
            }
        }

        this->mAdapter = adapter;
        this->mDevice = device;
    }

  protected:
    wgpu::Instance mInstance;
    wgpu::Adapter mAdapter;
    wgpu::Device mDevice;
    bool mGotCompatibilityMode = false;
};

INSTANTIATE_TEST_SUITE_P(,
                         SpotTests,
                         ::testing::ValuesIn({Mode::MinCompat, Mode::MaxCore}),
                         ::testing::PrintToStringParamName());

TEST_P(SpotTests, QuerySet) {
    // Spot test wgpuQuerySetGetType which uses indexOf on an int-to-string table.
    wgpu::QuerySetDescriptor querySetDesc{.type = wgpu::QueryType::Occlusion, .count = 1};
    wgpu::QuerySet querySet = mDevice.CreateQuerySet(&querySetDesc);
    EXPECT_TRUE(querySet);
    EXPECT_EQ(querySet.GetType(), querySetDesc.type);
}

TEST_P(SpotTests, BufferGetMapState) {
    // Spot test one of the string-to-int tables (Int_BufferMapState) to make sure
    // that Closure's minification didn't minify its keys.
    wgpu::BufferDescriptor bufferDesc{.usage = wgpu::BufferUsage::CopyDst, .size = 4};
    wgpu::Buffer buffer = mDevice.CreateBuffer(&bufferDesc);
    EXPECT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Unmapped);
}

TEST_P(SpotTests, GetCompilationInfo) {
    for (bool valid : {true, false}) {
        wgpu::ShaderSourceWGSL wgslDesc{};
        wgslDesc.code = valid ? "" : "some invalid code";

        wgpu::ShaderModuleDescriptor descriptor{};
        descriptor.nextInChain = &wgslDesc;
        auto sm = mDevice.CreateShaderModule(&descriptor);
        auto future = sm.GetCompilationInfo(
            wgpu::CallbackMode::WaitAnyOnly,
            [](wgpu::CompilationInfoRequestStatus, const wgpu::CompilationInfo* compilationInfo) {
                // We shouldn't have tried to allocate stuff if there were no messages.
                EXPECT_EQ(compilationInfo->messageCount == 0, compilationInfo->messages == nullptr);

                // After this, any compilation info will be freed. (There was a bug here which
                // this test catches, but only in ASAN builds.)
            });
        EXPECT_EQ(wgpu::WaitStatus::Success, mInstance.WaitAny(future, UINT64_MAX));
    }
}

TEST_P(SpotTests, ExternalRefCount) {
    wgpu::BufferDescriptor bufferDesc{
        .usage = wgpu::BufferUsage::MapRead, .size = 16, .mappedAtCreation = true};

    wgpu::Buffer buffer = mDevice.CreateBuffer(&bufferDesc);
    ASSERT_TRUE(buffer);
    EXPECT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Mapped);
    {
        // Add and then release an extra external ref.
        wgpu::Buffer tmp = buffer;
    }

    // Make sure the device wasn't implicitly destroyed (because we thought
    // the last external ref was dropped).
    EXPECT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Mapped);
}

TEST_P(SpotTests, InvalidComponentSwizzle) {
    wgpu::TextureDescriptor textureDesc = {};
    textureDesc.size = {1, 1, 0};
    textureDesc.usage = wgpu::TextureUsage::TextureBinding;
    textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
    wgpu::Texture texture = mDevice.CreateTexture(&textureDesc);

    wgpu::TextureViewDescriptor viewDesc = {};
    wgpu::TextureComponentSwizzleDescriptor swizzleDesc = {};
    // An invalid ComponentSwizzle value doesn't crash.
    swizzleDesc.swizzle.r = static_cast<wgpu::ComponentSwizzle>(-1);
    viewDesc.nextInChain = &swizzleDesc;
    wgpu::TextureView view = texture.CreateView(&viewDesc);
    ASSERT_TRUE(view);
}

TEST_P(SpotTests, GetWGSLLanguageFeatures) {
    wgpu::SupportedWGSLLanguageFeatures f;
    mInstance.GetWGSLLanguageFeatures(&f);
    auto features = DAWN_UNSAFE_TODO(std::span(f.features, f.featureCount));
    std::cout << "GetWGSLLanguageFeatures:\n";
    for (auto feature : features) {
        // GetWGSLLanguageFeatures should filter out any unknown features.
        EXPECT_NE(feature, wgpu::WGSLLanguageFeatureName{0});
        EXPECT_TRUE(mInstance.HasWGSLLanguageFeature(feature));
        std::cout << "  - " << feature << "\n";
    }

    // Test a specific feature to make sure minification worked.
    // WGSL feature names are valid JS identifiers (they use underscores instead
    // of hyphens), so they're vulnerable to Closure minification.
    if (EM_ASM_INT({
            return navigator.gpu.wgslLanguageFeatures.has('unrestricted_pointer_parameters');
        })) {
        auto feature = wgpu::WGSLLanguageFeatureName::UnrestrictedPointerParameters;
        EXPECT_NE(std::find(features.begin(), features.end(), feature), features.end());
        EXPECT_TRUE(mInstance.HasWGSLLanguageFeature(feature));
    }
}

template <typename AdapterOrDevice>
void TestGetFeatures(AdapterOrDevice o, bool shouldHaveCompressedTexture) {
    wgpu::SupportedFeatures f;
    o.GetFeatures(&f);
    auto features = DAWN_UNSAFE_TODO(std::span(f.features, f.featureCount));
    for (auto feature : features) {
        // GetFeatures should filter out any unknown features.
        EXPECT_NE(feature, wgpu::FeatureName{0});
        EXPECT_TRUE(o.HasFeature(feature));
    }

    // Test some specific features to make sure minification worked.
    bool haveCompressedTexture = false;
    if (EM_ASM_INT(
            { return WebGPU.getJsObject($0).features.has('texture-compression-bc'); }, o.Get())) {
        auto feature = wgpu::FeatureName::TextureCompressionBC;
        EXPECT_NE(std::find(features.begin(), features.end(), feature), features.end());
        EXPECT_TRUE(o.HasFeature(feature));
        haveCompressedTexture = true;
    }
    if (EM_ASM_INT(
            { return WebGPU.getJsObject($0).features.has('texture-compression-etc2'); }, o.Get())) {
        auto feature = wgpu::FeatureName::TextureCompressionETC2;
        EXPECT_NE(std::find(features.begin(), features.end(), feature), features.end());
        EXPECT_TRUE(o.HasFeature(feature));
        haveCompressedTexture = true;
    }
    EXPECT_EQ(haveCompressedTexture, shouldHaveCompressedTexture);

    // "subgroups" is a valid JS identifier (no hyphens), so it's
    // vulnerable to Closure minification.
    if (EM_ASM_INT({ return WebGPU.getJsObject($0).features.has('subgroups'); }, o.Get())) {
        auto feature = wgpu::FeatureName::Subgroups;
        EXPECT_NE(std::find(features.begin(), features.end(), feature), features.end());
        EXPECT_TRUE(o.HasFeature(feature));
    }
}

// Test GetFeatures and HasFeature enum lookups.
TEST_P(SpotTests, GetFeatures) {
    TestGetFeatures(mAdapter, true);
    TestGetFeatures(mDevice, GetParam() != Mode::MinCompat);
}

template <typename TStruct, typename TNumber>
void TestGetLimits(Mode mode,
                   const TStruct& adapterLimits,
                   const TStruct& deviceLimits,
                   const TNumber TStruct::* const field,
                   bool checkNonZero = true) {
    if (mode == Mode::MaxCore) {
        EXPECT_EQ(adapterLimits.*field, deviceLimits.*field);
    }

    // Check if left uninitialized
    EXPECT_NE(adapterLimits.*field, wgpu::kLimitU32Undefined);
    EXPECT_NE(deviceLimits.*field, wgpu::kLimitU32Undefined);

    // Check if missing from the browser
    if (checkNonZero) {
        EXPECT_NE(adapterLimits.*field, 0u);
        EXPECT_NE(deviceLimits.*field, 0u);
    }
}

TEST_P(SpotTests, Limits) {
    wgpu::Limits adapterLimits{};
    wgpu::CompatibilityModeLimits adapterCompatLimits{};
    adapterLimits.nextInChain = &adapterCompatLimits;

    wgpu::Limits deviceLimits{};
    wgpu::CompatibilityModeLimits deviceCompatLimits{};
    deviceLimits.nextInChain = &deviceCompatLimits;

    mAdapter.GetLimits(&adapterLimits);
    mDevice.GetLimits(&deviceLimits);

    // Core (1.0) limits
    for (int i = 0;  //
         uint32_t wgpu::Limits::* const field : {
             // WGPULimits is stable, so this list shouldn't grow in the future.
             // Extensions need to be tested separately.
             &wgpu::Limits::maxTextureDimension1D,
             &wgpu::Limits::maxTextureDimension2D,
             &wgpu::Limits::maxTextureDimension3D,
             &wgpu::Limits::maxTextureArrayLayers,
             &wgpu::Limits::maxBindGroups,
             &wgpu::Limits::maxBindGroupsPlusVertexBuffers,
             &wgpu::Limits::maxBindingsPerBindGroup,
             &wgpu::Limits::maxDynamicUniformBuffersPerPipelineLayout,
             &wgpu::Limits::maxDynamicStorageBuffersPerPipelineLayout,
             &wgpu::Limits::maxSampledTexturesPerShaderStage,
             &wgpu::Limits::maxSamplersPerShaderStage,
             &wgpu::Limits::maxStorageBuffersPerShaderStage,
             &wgpu::Limits::maxStorageTexturesPerShaderStage,
             &wgpu::Limits::maxUniformBuffersPerShaderStage,
             &wgpu::Limits::minUniformBufferOffsetAlignment,
             &wgpu::Limits::minStorageBufferOffsetAlignment,
             &wgpu::Limits::maxVertexBuffers,
             &wgpu::Limits::maxVertexAttributes,
             &wgpu::Limits::maxVertexBufferArrayStride,
             &wgpu::Limits::maxInterStageShaderVariables,
             &wgpu::Limits::maxColorAttachments,
             &wgpu::Limits::maxColorAttachmentBytesPerSample,
             &wgpu::Limits::maxComputeWorkgroupStorageSize,
             &wgpu::Limits::maxComputeInvocationsPerWorkgroup,
             &wgpu::Limits::maxComputeWorkgroupSizeX,
             &wgpu::Limits::maxComputeWorkgroupSizeY,
             &wgpu::Limits::maxComputeWorkgroupSizeZ,
             &wgpu::Limits::maxComputeWorkgroupsPerDimension,
             &wgpu::Limits::maxImmediateSize,
         }) {
        SCOPED_TRACE(absl::StrFormat("Limits 32 case %d", i++));
        bool checkNonZero = field != &wgpu::Limits::maxImmediateSize;
        TestGetLimits(GetParam(), adapterLimits, deviceLimits, field, checkNonZero);
    }

    // Core 64-bit limits
    for (int i = 0;  //
         uint64_t wgpu::Limits::* const field : {
             &wgpu::Limits::maxUniformBufferBindingSize,
             &wgpu::Limits::maxStorageBufferBindingSize,
             &wgpu::Limits::maxBufferSize,
         }) {
        SCOPED_TRACE(absl::StrFormat("Limits 64 case %d", i++).c_str());
        TestGetLimits(GetParam(), adapterLimits, deviceLimits, field);
    }

    // CompatibilityModeLimits extension
    for (int i = 0;  //
         uint32_t wgpu::CompatibilityModeLimits::* const field : {
             // WGPUCompatibilityModeLimits is becoming stable, so this list shouldn't grow.
             &wgpu::CompatibilityModeLimits::maxStorageBuffersInVertexStage,
             &wgpu::CompatibilityModeLimits::maxStorageTexturesInVertexStage,
             &wgpu::CompatibilityModeLimits::maxStorageBuffersInFragmentStage,
             &wgpu::CompatibilityModeLimits::maxStorageTexturesInFragmentStage,
         }) {
        SCOPED_TRACE(absl::StrFormat("CompatibilityModeLimits case %d", i++).c_str());
        bool checkNonZero =
            field != &wgpu::CompatibilityModeLimits::maxStorageBuffersInVertexStage &&
            field != &wgpu::CompatibilityModeLimits::maxStorageTexturesInVertexStage;
        TestGetLimits(GetParam(), adapterCompatLimits, deviceCompatLimits, field, checkNonZero);
    }
}

TEST_P(SpotTests, ImportExternalTexture) {
    auto cExternalTexture = static_cast<WGPUExternalTexture>(EM_ASM_PTR(
        {
            const cDevice = $0;
            const device = WebGPU.getJsObject(cDevice);

            const cvs = document.createElement('canvas');
            cvs.width = 1;
            cvs.height = 1;
            const ctx = cvs.getContext('2d');
            ctx.fillStyle = '#0f0';
            ctx.fillRect(0, 0, 1, 1);
            window.myVideoFrame = new VideoFrame(cvs, {timestamp : 0});

            const jsExternalTexture = device.importExternalTexture({source : window.myVideoFrame});
            const cExternalTexture = WebGPU.importJsExternalTexture(jsExternalTexture);
            return cExternalTexture;
        },
        mDevice.Get()));
    auto externalTexture = wgpu::ExternalTexture::Acquire(cExternalTexture);

    wgpu::BufferDescriptor bufferDesc{
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(uint32_t),
    };
    auto buffer = mDevice.CreateBuffer(&bufferDesc);

    wgpu::BufferDescriptor readbackDesc{
        .usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead,
        .size = sizeof(uint32_t),
    };
    auto readback = mDevice.CreateBuffer(&readbackDesc);

    wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
        mDevice, {{0, wgpu::ShaderStage::Compute, &utils::kExternalTextureBindingLayout},
                  {1, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Storage}});
    wgpu::BindGroup bg = utils::MakeBindGroup(mDevice, bgl, {{0, externalTexture}, {1, buffer}});

    auto module = utils::CreateShaderModule(mDevice, R"(
        @group(0) @binding(0) var t: texture_external;
        @group(0) @binding(1) var<storage, read_write> b: u32;

        @compute @workgroup_size(1) fn main() {
            b = pack4x8unorm(textureLoad(t, vec2u(0, 0)));
        })");

    wgpu::ComputePipelineDescriptor pipelineDesc{
        .layout = utils::MakeBasicPipelineLayout(mDevice, &bgl),
        .compute = {.module = module},
    };
    auto pipeline = mDevice.CreateComputePipeline(&pipelineDesc);

    auto encoder = mDevice.CreateCommandEncoder();
    {
        auto pass = encoder.BeginComputePass();
        pass.SetBindGroup(0, bg);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();
    }
    encoder.CopyBufferToBuffer(buffer, 0, readback, 0, sizeof(uint32_t));
    auto commandBuffer = encoder.Finish();
    mDevice.GetQueue().Submit(1, &commandBuffer);

    // Note we can't (yet) use EXPECT_BUFFER_U32_EQ here.
    uint32_t result = 0;
    mInstance.WaitAny(
        readback.MapAsync(
            wgpu::MapMode::Read, 0, wgpu::kWholeMapSize, wgpu::CallbackMode::WaitAnyOnly,
            [&](wgpu::MapAsyncStatus, wgpu::StringView) {
                result = static_cast<const uint32_t*>(readback.GetConstMappedRange())[0];
                readback.Unmap();
            }),
        UINT64_MAX);
    EXPECT_EQ(result, uint32_t(0xff00ff00));  // ABGR

    EM_ASM({
        // VideoFrames should always be closed manually.
        window.myVideoFrame.close();
        delete window.myVideoFrame;
    });
}

TEST_P(SpotTests, ImportBuffer) {
    auto cBuffer = static_cast<WGPUBuffer>(EM_ASM_PTR(
        {
            const cDevice = $0;
            const device = WebGPU.getJsObject(cDevice);

            const jsBuffer = device.createBuffer({size : 4, usage : GPUBufferUsage.COPY_SRC});
            const cBuffer = WebGPU.importJsBuffer(jsBuffer);
            return cBuffer;
        },
        mDevice.Get()));
    auto buffer = wgpu::Buffer::Acquire(cBuffer);
}

TEST_P(SpotTests, MapReadGetMappedRange) {
    wgpu::BufferDescriptor readbackDesc{
        .usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead,
        .size = sizeof(uint32_t),
    };
    auto buffer = mDevice.CreateBuffer(&readbackDesc);

    mInstance.WaitAny(buffer.MapAsync(wgpu::MapMode::Read, 0, wgpu::kWholeMapSize,
                                      wgpu::CallbackMode::WaitAnyOnly,
                                      [&](wgpu::MapAsyncStatus, wgpu::StringView) {
                                          EXPECT_EQ(buffer.GetMappedRange(), nullptr);
                                          EXPECT_NE(buffer.GetConstMappedRange(), nullptr);
                                          buffer.Unmap();
                                      }),
                      UINT64_MAX);
}

// This test requires compat (chromium 146+). Other tests should be written to work without it.
TEST_P(SpotTests, FeatureLevelHonored) {
    EXPECT_EQ(mGotCompatibilityMode, GetParam() == Mode::MinCompat);
}

TEST_P(SpotTests, TextureBindingViewDimension) {
    wgpu::TextureDescriptor textureDesc;
    textureDesc.size = {1, 1, 1};
    textureDesc.usage = wgpu::TextureUsage::RenderAttachment;
    textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;

    wgpu::TextureBindingViewDimension textureBindingViewDimensionDesc;
    textureBindingViewDimensionDesc.textureBindingViewDimension =
        wgpu::TextureViewDimension::e2DArray;
    textureDesc.nextInChain = &textureBindingViewDimensionDesc;
    wgpu::Texture texture = mDevice.CreateTexture(&textureDesc);

    ASSERT_TRUE(texture);
    EXPECT_EQ(texture.GetTextureBindingViewDimension(),
              mGotCompatibilityMode ? textureBindingViewDimensionDesc.textureBindingViewDimension
                                    : wgpu::TextureViewDimension::Undefined);
}

TEST_P(SpotTests, AdapterInfo) {
    wgpu::AdapterPropertiesSubgroupMatrixConfigs extConfigs;
    wgpu::AdapterInfo info;
    info.nextInChain = &extConfigs;

    mAdapter.GetInfo(&info);
    std::cout << "AdapterInfo:\n  ";
    std::cout << info.vendor << ", " << info.architecture << ", " << info.device << ", "
              << info.description << ",\n  ";
    std::cout << info.backendType << ", " << info.adapterType << ",\n  ";
    std::cout << info.vendorID << ", " << info.deviceID << ",\n  ";
    std::cout << info.subgroupMinSize << ", " << info.subgroupMaxSize << "\n";
    std::cout << "AdapterPropertiesSubgroupMatrixConfigs:\n";
    for (auto cfg : DAWN_UNSAFE_TODO(std::span(extConfigs.configs, extConfigs.configCount))) {
        std::cout << "  - " << cfg.componentType << ", " << cfg.resultComponentType << ", " << cfg.M
                  << ", " << cfg.N << ", " << cfg.K << "\n";
    }
}

TEST_P(SpotTests, AdapterFeatures) {
    wgpu::SupportedFeatures features;
    mAdapter.GetFeatures(&features);
    std::cout << "Adapter features:\n";
    for (auto feature : DAWN_UNSAFE_TODO(std::span(features.features, features.featureCount))) {
        std::cout << "  - " << feature << "\n";
    }
}

TEST_P(SpotTests, DeviceFeatures) {
    wgpu::SupportedFeatures features;
    mDevice.GetFeatures(&features);
    std::cout << "Device features:\n";
    for (auto feature : DAWN_UNSAFE_TODO(std::span(features.features, features.featureCount))) {
        std::cout << "  - " << feature << "\n";
    }
}

}  // namespace
