// 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 "tests/unittests/wire/WireTest.h"

using namespace testing;
using namespace dawn::wire;

class WireOptionalTests : public WireTest {
  public:
    WireOptionalTests() {
    }
    ~WireOptionalTests() override = default;
};

// Test passing nullptr instead of objects - object as value version
TEST_F(WireOptionalTests, OptionalObjectValue) {
    WGPUBindGroupLayoutDescriptor bglDesc = {};
    bglDesc.entryCount = 0;
    WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device, &bglDesc);

    WGPUBindGroupLayout apiBindGroupLayout = api.GetNewBindGroupLayout();
    EXPECT_CALL(api, DeviceCreateBindGroupLayout(apiDevice, _))
        .WillOnce(Return(apiBindGroupLayout));

    // The `sampler`, `textureView` and `buffer` members of a binding are optional.
    WGPUBindGroupEntry entry;
    entry.binding = 0;
    entry.sampler = nullptr;
    entry.textureView = nullptr;
    entry.buffer = nullptr;
    entry.nextInChain = nullptr;

    WGPUBindGroupDescriptor bgDesc = {};
    bgDesc.layout = bgl;
    bgDesc.entryCount = 1;
    bgDesc.entries = &entry;

    wgpuDeviceCreateBindGroup(device, &bgDesc);

    WGPUBindGroup apiDummyBindGroup = api.GetNewBindGroup();
    EXPECT_CALL(api, DeviceCreateBindGroup(
                         apiDevice, MatchesLambda([](const WGPUBindGroupDescriptor* desc) -> bool {
                             return desc->nextInChain == nullptr && desc->entryCount == 1 &&
                                    desc->entries[0].binding == 0 &&
                                    desc->entries[0].sampler == nullptr &&
                                    desc->entries[0].buffer == nullptr &&
                                    desc->entries[0].textureView == nullptr;
                         })))
        .WillOnce(Return(apiDummyBindGroup));

    FlushClient();
}

// Test that the wire is able to send optional pointers to structures
TEST_F(WireOptionalTests, OptionalStructPointer) {
    // Create shader module
    WGPUShaderModuleDescriptor vertexDescriptor = {};
    WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
    WGPUShaderModule apiVsModule = api.GetNewShaderModule();
    EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _)).WillOnce(Return(apiVsModule));

    // Create the color state descriptor
    WGPUBlendComponent blendComponent = {};
    blendComponent.operation = WGPUBlendOperation_Add;
    blendComponent.srcFactor = WGPUBlendFactor_One;
    blendComponent.dstFactor = WGPUBlendFactor_One;
    WGPUBlendState blendState = {};
    blendState.alpha = blendComponent;
    blendState.color = blendComponent;
    WGPUColorTargetState colorTargetState = {};
    colorTargetState.format = WGPUTextureFormat_RGBA8Unorm;
    colorTargetState.blend = &blendState;
    colorTargetState.writeMask = WGPUColorWriteMask_All;

    // Create the depth-stencil state
    WGPUStencilFaceState stencilFace = {};
    stencilFace.compare = WGPUCompareFunction_Always;
    stencilFace.failOp = WGPUStencilOperation_Keep;
    stencilFace.depthFailOp = WGPUStencilOperation_Keep;
    stencilFace.passOp = WGPUStencilOperation_Keep;

    WGPUDepthStencilState depthStencilState = {};
    depthStencilState.format = WGPUTextureFormat_Depth24PlusStencil8;
    depthStencilState.depthWriteEnabled = false;
    depthStencilState.depthCompare = WGPUCompareFunction_Always;
    depthStencilState.stencilBack = stencilFace;
    depthStencilState.stencilFront = stencilFace;
    depthStencilState.stencilReadMask = 0xff;
    depthStencilState.stencilWriteMask = 0xff;
    depthStencilState.depthBias = 0;
    depthStencilState.depthBiasSlopeScale = 0.0;
    depthStencilState.depthBiasClamp = 0.0;

    // Create the pipeline layout
    WGPUPipelineLayoutDescriptor layoutDescriptor = {};
    layoutDescriptor.bindGroupLayoutCount = 0;
    layoutDescriptor.bindGroupLayouts = nullptr;
    WGPUPipelineLayout layout = wgpuDeviceCreatePipelineLayout(device, &layoutDescriptor);
    WGPUPipelineLayout apiLayout = api.GetNewPipelineLayout();
    EXPECT_CALL(api, DeviceCreatePipelineLayout(apiDevice, _)).WillOnce(Return(apiLayout));

    // Create pipeline
    WGPURenderPipelineDescriptor pipelineDescriptor = {};

    pipelineDescriptor.vertex.module = vsModule;
    pipelineDescriptor.vertex.entryPoint = "main";
    pipelineDescriptor.vertex.bufferCount = 0;
    pipelineDescriptor.vertex.buffers = nullptr;

    WGPUFragmentState fragment = {};
    fragment.module = vsModule;
    fragment.entryPoint = "main";
    fragment.targetCount = 1;
    fragment.targets = &colorTargetState;
    pipelineDescriptor.fragment = &fragment;

    pipelineDescriptor.multisample.count = 1;
    pipelineDescriptor.multisample.mask = 0xFFFFFFFF;
    pipelineDescriptor.multisample.alphaToCoverageEnabled = false;
    pipelineDescriptor.layout = layout;
    pipelineDescriptor.primitive.topology = WGPUPrimitiveTopology_TriangleList;
    pipelineDescriptor.primitive.frontFace = WGPUFrontFace_CCW;
    pipelineDescriptor.primitive.cullMode = WGPUCullMode_None;

    // First case: depthStencil is not null.
    pipelineDescriptor.depthStencil = &depthStencilState;
    wgpuDeviceCreateRenderPipeline(device, &pipelineDescriptor);

    WGPURenderPipeline apiDummyPipeline = api.GetNewRenderPipeline();
    EXPECT_CALL(
        api,
        DeviceCreateRenderPipeline(
            apiDevice, MatchesLambda([](const WGPURenderPipelineDescriptor* desc) -> bool {
                return desc->depthStencil != nullptr &&
                       desc->depthStencil->nextInChain == nullptr &&
                       desc->depthStencil->depthWriteEnabled == false &&
                       desc->depthStencil->depthCompare == WGPUCompareFunction_Always &&
                       desc->depthStencil->stencilBack.compare == WGPUCompareFunction_Always &&
                       desc->depthStencil->stencilBack.failOp == WGPUStencilOperation_Keep &&
                       desc->depthStencil->stencilBack.depthFailOp == WGPUStencilOperation_Keep &&
                       desc->depthStencil->stencilBack.passOp == WGPUStencilOperation_Keep &&
                       desc->depthStencil->stencilFront.compare == WGPUCompareFunction_Always &&
                       desc->depthStencil->stencilFront.failOp == WGPUStencilOperation_Keep &&
                       desc->depthStencil->stencilFront.depthFailOp == WGPUStencilOperation_Keep &&
                       desc->depthStencil->stencilFront.passOp == WGPUStencilOperation_Keep &&
                       desc->depthStencil->stencilReadMask == 0xff &&
                       desc->depthStencil->stencilWriteMask == 0xff &&
                       desc->depthStencil->depthBias == 0 &&
                       desc->depthStencil->depthBiasSlopeScale == 0.0 &&
                       desc->depthStencil->depthBiasClamp == 0.0;
            })))
        .WillOnce(Return(apiDummyPipeline));

    FlushClient();

    // Second case: depthStencil is null.
    pipelineDescriptor.depthStencil = nullptr;
    wgpuDeviceCreateRenderPipeline(device, &pipelineDescriptor);
    EXPECT_CALL(api,
                DeviceCreateRenderPipeline(
                    apiDevice, MatchesLambda([](const WGPURenderPipelineDescriptor* desc) -> bool {
                        return desc->depthStencil == nullptr;
                    })))
        .WillOnce(Return(apiDummyPipeline));

    FlushClient();
}
