// 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
