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