// Copyright 2021 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"

#include "dawn_wire/WireClient.h"
#include "dawn_wire/WireServer.h"

using namespace testing;
using namespace dawn_wire;

namespace {

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

    // Test that reserving and injecting an instance makes calls on the client object forward to the
    // server object correctly.
    TEST_F(WireInjectInstanceTests, CallAfterReserveInject) {
        ReservedInstance reservation = GetWireClient()->ReserveInstance();

        WGPUInstance serverInstance = api.GetNewInstance();
        EXPECT_CALL(api, InstanceReference(serverInstance));
        ASSERT_TRUE(
            GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));

        WGPUSurfaceDescriptor surfaceDesc = {};
        wgpuInstanceCreateSurface(reservation.instance, &surfaceDesc);
        WGPUSurface serverSurface = api.GetNewSurface();
        EXPECT_CALL(api, InstanceCreateSurface(serverInstance, NotNull())).WillOnce(Return(serverSurface));
        FlushClient();
    }

    // Test that reserve correctly returns different IDs each time.
    TEST_F(WireInjectInstanceTests, ReserveDifferentIDs) {
        ReservedInstance reservation1 = GetWireClient()->ReserveInstance();
        ReservedInstance reservation2 = GetWireClient()->ReserveInstance();

        ASSERT_NE(reservation1.id, reservation2.id);
        ASSERT_NE(reservation1.instance, reservation2.instance);
    }


    // Test that injecting the same id fails.
    TEST_F(WireInjectInstanceTests, InjectExistingID) {
        ReservedInstance reservation = GetWireClient()->ReserveInstance();

        WGPUInstance serverInstance = api.GetNewInstance();
        EXPECT_CALL(api, InstanceReference(serverInstance));
        ASSERT_TRUE(
            GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));

        // ID already in use, call fails.
        ASSERT_FALSE(
            GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
    }

    // Test that the server only borrows the instance and does a single reference-release
    TEST_F(WireInjectInstanceTests, InjectedInstanceLifetime) {
        ReservedInstance reservation = GetWireClient()->ReserveInstance();

        // Injecting the instance adds a reference
        WGPUInstance serverInstance = api.GetNewInstance();
        EXPECT_CALL(api, InstanceReference(serverInstance));
        ASSERT_TRUE(
            GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));

        // Releasing the instance removes a single reference.
        wgpuInstanceRelease(reservation.instance);
        EXPECT_CALL(api, InstanceRelease(serverInstance));
        FlushClient();

        // Deleting the server doesn't release a second reference.
        DeleteServer();
        Mock::VerifyAndClearExpectations(&api);
    }

    // Test that a device reservation can be reclaimed. This is necessary to
    // avoid leaking ObjectIDs for reservations that are never injected.
    TEST_F(WireInjectInstanceTests, ReclaimInstanceReservation) {
        // Test that doing a reservation and full release is an error.
        {
            ReservedInstance reservation = GetWireClient()->ReserveInstance();
            wgpuInstanceRelease(reservation.instance);
            FlushClient(false);
        }

        // Test that doing a reservation and then reclaiming it recycles the ID.
        {
            ReservedInstance reservation1 = GetWireClient()->ReserveInstance();
            GetWireClient()->ReclaimInstanceReservation(reservation1);

            ReservedInstance reservation2 = GetWireClient()->ReserveInstance();

            // The ID is the same, but the generation is still different.
            ASSERT_EQ(reservation1.id, reservation2.id);
            ASSERT_NE(reservation1.generation, reservation2.generation);

            // No errors should occur.
            FlushClient();
        }
    }

}  // anonymous namespace
