// Copyright 2018 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 <gtest/gtest.h>

#include "dawn_native/Error.h"
#include "dawn_native/ErrorData.h"

using namespace dawn::native;

namespace {

    int dummySuccess = 0xbeef;
    const char* dummyErrorMessage = "I am an error message :3";

    // Check returning a success MaybeError with {};
    TEST(ErrorTests, Error_Success) {
        auto ReturnSuccess = []() -> MaybeError { return {}; };

        MaybeError result = ReturnSuccess();
        ASSERT_TRUE(result.IsSuccess());
    }

    // Check returning an error MaybeError with "return DAWN_VALIDATION_ERROR"
    TEST(ErrorTests, Error_Error) {
        auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };

        MaybeError result = ReturnError();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

    // Check returning a success ResultOrError with an implicit conversion
    TEST(ErrorTests, ResultOrError_Success) {
        auto ReturnSuccess = []() -> ResultOrError<int*> { return &dummySuccess; };

        ResultOrError<int*> result = ReturnSuccess();
        ASSERT_TRUE(result.IsSuccess());
        ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
    }

    // Check returning an error ResultOrError with "return DAWN_VALIDATION_ERROR"
    TEST(ErrorTests, ResultOrError_Error) {
        auto ReturnError = []() -> ResultOrError<int*> {
            return DAWN_VALIDATION_ERROR(dummyErrorMessage);
        };

        ResultOrError<int*> result = ReturnError();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

    // Check DAWN_TRY handles successes correctly.
    TEST(ErrorTests, TRY_Success) {
        auto ReturnSuccess = []() -> MaybeError { return {}; };

        // We need to check that DAWN_TRY doesn't return on successes
        bool tryReturned = true;

        auto Try = [ReturnSuccess, &tryReturned]() -> MaybeError {
            DAWN_TRY(ReturnSuccess());
            tryReturned = false;
            return {};
        };

        MaybeError result = Try();
        ASSERT_TRUE(result.IsSuccess());
        ASSERT_FALSE(tryReturned);
    }

    // Check DAWN_TRY handles errors correctly.
    TEST(ErrorTests, TRY_Error) {
        auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };

        auto Try = [ReturnError]() -> MaybeError {
            DAWN_TRY(ReturnError());
            // DAWN_TRY should return before this point
            EXPECT_FALSE(true);
            return {};
        };

        MaybeError result = Try();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

    // Check DAWN_TRY adds to the backtrace.
    TEST(ErrorTests, TRY_AddsToBacktrace) {
        auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };

        auto SingleTry = [ReturnError]() -> MaybeError {
            DAWN_TRY(ReturnError());
            return {};
        };

        auto DoubleTry = [SingleTry]() -> MaybeError {
            DAWN_TRY(SingleTry());
            return {};
        };

        MaybeError singleResult = SingleTry();
        ASSERT_TRUE(singleResult.IsError());

        MaybeError doubleResult = DoubleTry();
        ASSERT_TRUE(doubleResult.IsError());

        std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
        std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();

        ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
    }

    // Check DAWN_TRY_ASSIGN handles successes correctly.
    TEST(ErrorTests, TRY_RESULT_Success) {
        auto ReturnSuccess = []() -> ResultOrError<int*> { return &dummySuccess; };

        // We need to check that DAWN_TRY doesn't return on successes
        bool tryReturned = true;

        auto Try = [ReturnSuccess, &tryReturned]() -> ResultOrError<int*> {
            int* result = nullptr;
            DAWN_TRY_ASSIGN(result, ReturnSuccess());
            tryReturned = false;

            EXPECT_EQ(result, &dummySuccess);
            return result;
        };

        ResultOrError<int*> result = Try();
        ASSERT_TRUE(result.IsSuccess());
        ASSERT_FALSE(tryReturned);
        ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
    }

    // Check DAWN_TRY_ASSIGN handles errors correctly.
    TEST(ErrorTests, TRY_RESULT_Error) {
        auto ReturnError = []() -> ResultOrError<int*> {
            return DAWN_VALIDATION_ERROR(dummyErrorMessage);
        };

        auto Try = [ReturnError]() -> ResultOrError<int*> {
            int* result = nullptr;
            DAWN_TRY_ASSIGN(result, ReturnError());
            DAWN_UNUSED(result);

            // DAWN_TRY should return before this point
            EXPECT_FALSE(true);
            return &dummySuccess;
        };

        ResultOrError<int*> result = Try();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

    // Check DAWN_TRY_ASSIGN adds to the backtrace.
    TEST(ErrorTests, TRY_RESULT_AddsToBacktrace) {
        auto ReturnError = []() -> ResultOrError<int*> {
            return DAWN_VALIDATION_ERROR(dummyErrorMessage);
        };

        auto SingleTry = [ReturnError]() -> ResultOrError<int*> {
            DAWN_TRY(ReturnError());
            return &dummySuccess;
        };

        auto DoubleTry = [SingleTry]() -> ResultOrError<int*> {
            DAWN_TRY(SingleTry());
            return &dummySuccess;
        };

        ResultOrError<int*> singleResult = SingleTry();
        ASSERT_TRUE(singleResult.IsError());

        ResultOrError<int*> doubleResult = DoubleTry();
        ASSERT_TRUE(doubleResult.IsError());

        std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
        std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();

        ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
    }

    // Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
    TEST(ErrorTests, TRY_RESULT_ConversionToError) {
        auto ReturnError = []() -> ResultOrError<int*> {
            return DAWN_VALIDATION_ERROR(dummyErrorMessage);
        };

        auto Try = [ReturnError]() -> MaybeError {
            int* result = nullptr;
            DAWN_TRY_ASSIGN(result, ReturnError());
            DAWN_UNUSED(result);

            return {};
        };

        MaybeError result = Try();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

    // Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
    // Version without Result<E*, T*>
    TEST(ErrorTests, TRY_RESULT_ConversionToErrorNonPointer) {
        auto ReturnError = []() -> ResultOrError<int> {
            return DAWN_VALIDATION_ERROR(dummyErrorMessage);
        };

        auto Try = [ReturnError]() -> MaybeError {
            int result = 0;
            DAWN_TRY_ASSIGN(result, ReturnError());
            DAWN_UNUSED(result);

            return {};
        };

        MaybeError result = Try();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

    // Check DAWN_TRY_ASSIGN handles successes correctly.
    TEST(ErrorTests, TRY_RESULT_CLEANUP_Success) {
        auto ReturnSuccess = []() -> ResultOrError<int*> { return &dummySuccess; };

        // We need to check that DAWN_TRY_ASSIGN_WITH_CLEANUP doesn't return on successes and the
        // cleanup is not called.
        bool tryReturned = true;
        bool tryCleanup = false;

        auto Try = [ReturnSuccess, &tryReturned, &tryCleanup]() -> ResultOrError<int*> {
            int* result = nullptr;
            DAWN_TRY_ASSIGN_WITH_CLEANUP(result, ReturnSuccess(), { tryCleanup = true; });
            tryReturned = false;

            EXPECT_EQ(result, &dummySuccess);
            return result;
        };

        ResultOrError<int*> result = Try();
        ASSERT_TRUE(result.IsSuccess());
        ASSERT_FALSE(tryReturned);
        ASSERT_FALSE(tryCleanup);
        ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
    }

    // Check DAWN_TRY_ASSIGN handles cleanups.
    TEST(ErrorTests, TRY_RESULT_CLEANUP_Cleanup) {
        auto ReturnError = []() -> ResultOrError<int*> {
            return DAWN_VALIDATION_ERROR(dummyErrorMessage);
        };

        // We need to check that DAWN_TRY_ASSIGN_WITH_CLEANUP calls cleanup when error.
        bool tryCleanup = false;

        auto Try = [ReturnError, &tryCleanup]() -> ResultOrError<int*> {
            int* result = nullptr;
            DAWN_TRY_ASSIGN_WITH_CLEANUP(result, ReturnError(), { tryCleanup = true; });
            DAWN_UNUSED(result);

            // DAWN_TRY_ASSIGN_WITH_CLEANUP should return before this point
            EXPECT_FALSE(true);
            return &dummySuccess;
        };

        ResultOrError<int*> result = Try();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
        ASSERT_TRUE(tryCleanup);
    }

    // Check DAWN_TRY_ASSIGN can override return value when needed.
    TEST(ErrorTests, TRY_RESULT_CLEANUP_OverrideReturn) {
        auto ReturnError = []() -> ResultOrError<int*> {
            return DAWN_VALIDATION_ERROR(dummyErrorMessage);
        };

        auto Try = [ReturnError]() -> bool {
            int* result = nullptr;
            DAWN_TRY_ASSIGN_WITH_CLEANUP(result, ReturnError(), {}, true);
            DAWN_UNUSED(result);

            // DAWN_TRY_ASSIGN_WITH_CLEANUP should return before this point
            EXPECT_FALSE(true);
            return false;
        };

        bool result = Try();
        ASSERT_TRUE(result);
    }

    // Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
    // Check DAWN_TRY handles errors correctly.
    TEST(ErrorTests, TRY_ConversionToErrorOrResult) {
        auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };

        auto Try = [ReturnError]() -> ResultOrError<int*> {
            DAWN_TRY(ReturnError());
            return &dummySuccess;
        };

        ResultOrError<int*> result = Try();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

    // Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
    // Check DAWN_TRY handles errors correctly. Version without Result<E*, T*>
    TEST(ErrorTests, TRY_ConversionToErrorOrResultNonPointer) {
        auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };

        auto Try = [ReturnError]() -> ResultOrError<int> {
            DAWN_TRY(ReturnError());
            return 42;
        };

        ResultOrError<int> result = Try();
        ASSERT_TRUE(result.IsError());

        std::unique_ptr<ErrorData> errorData = result.AcquireError();
        ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
    }

}  // anonymous namespace
