mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-16 12:21:35 +00:00
Bug: none Change-Id: I69904944db1d4c2fbcca74bb8b66b5a7524e76bb Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24642 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Kai Ninomiya <kainino@chromium.org>
386 lines
13 KiB
C++
386 lines
13 KiB
C++
// 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 "common/RefCounted.h"
|
|
#include "common/Result.h"
|
|
|
|
namespace {
|
|
|
|
template <typename T, typename E>
|
|
void TestError(Result<T, E>* result, E expectedError) {
|
|
EXPECT_TRUE(result->IsError());
|
|
EXPECT_FALSE(result->IsSuccess());
|
|
|
|
std::unique_ptr<E> storedError = result->AcquireError();
|
|
EXPECT_EQ(*storedError, expectedError);
|
|
}
|
|
|
|
template <typename T, typename E>
|
|
void TestSuccess(Result<T, E>* result, T expectedSuccess) {
|
|
EXPECT_FALSE(result->IsError());
|
|
EXPECT_TRUE(result->IsSuccess());
|
|
|
|
const T storedSuccess = result->AcquireSuccess();
|
|
EXPECT_EQ(storedSuccess, expectedSuccess);
|
|
|
|
// Once the success is acquired, result has an empty
|
|
// payload and is neither in the success nor error state.
|
|
EXPECT_FALSE(result->IsError());
|
|
EXPECT_FALSE(result->IsSuccess());
|
|
}
|
|
|
|
static int dummyError = 0xbeef;
|
|
static float dummySuccess = 42.0f;
|
|
static const float dummyConstSuccess = 42.0f;
|
|
|
|
class AClass : public RefCounted {
|
|
public:
|
|
int a = 0;
|
|
};
|
|
|
|
// Tests using the following overload of TestSuccess make
|
|
// local Ref instances to dummySuccessObj. Tests should
|
|
// ensure any local Ref objects made along the way continue
|
|
// to point to dummySuccessObj.
|
|
template <typename T, typename E>
|
|
void TestSuccess(Result<Ref<T>, E>* result, T* expectedSuccess) {
|
|
EXPECT_FALSE(result->IsError());
|
|
EXPECT_TRUE(result->IsSuccess());
|
|
|
|
// AClass starts with a reference count of 1 and stored
|
|
// on the stack in the caller. The result parameter should
|
|
// hold the only other reference to the object.
|
|
EXPECT_EQ(expectedSuccess->GetRefCountForTesting(), 2u);
|
|
|
|
const Ref<T> storedSuccess = result->AcquireSuccess();
|
|
EXPECT_EQ(storedSuccess.Get(), expectedSuccess);
|
|
|
|
// Once the success is acquired, result has an empty
|
|
// payload and is neither in the success nor error state.
|
|
EXPECT_FALSE(result->IsError());
|
|
EXPECT_FALSE(result->IsSuccess());
|
|
|
|
// Once we call AcquireSuccess, result no longer stores
|
|
// the object. storedSuccess should contain the only other
|
|
// reference to the object.
|
|
EXPECT_EQ(storedSuccess->GetRefCountForTesting(), 2u);
|
|
}
|
|
|
|
// Result<void, E*>
|
|
|
|
// Test constructing an error Result<void, E>
|
|
TEST(ResultOnlyPointerError, ConstructingError) {
|
|
Result<void, int> result(std::make_unique<int>(dummyError));
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test moving an error Result<void, E>
|
|
TEST(ResultOnlyPointerError, MovingError) {
|
|
Result<void, int> result(std::make_unique<int>(dummyError));
|
|
Result<void, int> movedResult(std::move(result));
|
|
TestError(&movedResult, dummyError);
|
|
}
|
|
|
|
// Test returning an error Result<void, E>
|
|
TEST(ResultOnlyPointerError, ReturningError) {
|
|
auto CreateError = []() -> Result<void, int> {
|
|
return {std::make_unique<int>(dummyError)};
|
|
};
|
|
|
|
Result<void, int> result = CreateError();
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test constructing a success Result<void, E>
|
|
TEST(ResultOnlyPointerError, ConstructingSuccess) {
|
|
Result<void, int> result;
|
|
EXPECT_TRUE(result.IsSuccess());
|
|
EXPECT_FALSE(result.IsError());
|
|
}
|
|
|
|
// Test moving a success Result<void, E>
|
|
TEST(ResultOnlyPointerError, MovingSuccess) {
|
|
Result<void, int> result;
|
|
Result<void, int> movedResult(std::move(result));
|
|
EXPECT_TRUE(movedResult.IsSuccess());
|
|
EXPECT_FALSE(movedResult.IsError());
|
|
}
|
|
|
|
// Test returning a success Result<void, E>
|
|
TEST(ResultOnlyPointerError, ReturningSuccess) {
|
|
auto CreateError = []() -> Result<void, int> { return {}; };
|
|
|
|
Result<void, int> result = CreateError();
|
|
EXPECT_TRUE(result.IsSuccess());
|
|
EXPECT_FALSE(result.IsError());
|
|
}
|
|
|
|
// Result<T*, E*>
|
|
|
|
// Test constructing an error Result<T*, E>
|
|
TEST(ResultBothPointer, ConstructingError) {
|
|
Result<float*, int> result(std::make_unique<int>(dummyError));
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test moving an error Result<T*, E>
|
|
TEST(ResultBothPointer, MovingError) {
|
|
Result<float*, int> result(std::make_unique<int>(dummyError));
|
|
Result<float*, int> movedResult(std::move(result));
|
|
TestError(&movedResult, dummyError);
|
|
}
|
|
|
|
// Test returning an error Result<T*, E>
|
|
TEST(ResultBothPointer, ReturningError) {
|
|
auto CreateError = []() -> Result<float*, int> {
|
|
return {std::make_unique<int>(dummyError)};
|
|
};
|
|
|
|
Result<float*, int> result = CreateError();
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test constructing a success Result<T*, E>
|
|
TEST(ResultBothPointer, ConstructingSuccess) {
|
|
Result<float*, int> result(&dummySuccess);
|
|
TestSuccess(&result, &dummySuccess);
|
|
}
|
|
|
|
// Test moving a success Result<T*, E>
|
|
TEST(ResultBothPointer, MovingSuccess) {
|
|
Result<float*, int> result(&dummySuccess);
|
|
Result<float*, int> movedResult(std::move(result));
|
|
TestSuccess(&movedResult, &dummySuccess);
|
|
}
|
|
|
|
// Test returning a success Result<T*, E>
|
|
TEST(ResultBothPointer, ReturningSuccess) {
|
|
auto CreateSuccess = []() -> Result<float*, int*> { return {&dummySuccess}; };
|
|
|
|
Result<float*, int*> result = CreateSuccess();
|
|
TestSuccess(&result, &dummySuccess);
|
|
}
|
|
|
|
// Tests converting from a Result<TChild*, E>
|
|
TEST(ResultBothPointer, ConversionFromChildClass) {
|
|
struct T {
|
|
int a;
|
|
};
|
|
struct TChild : T {};
|
|
|
|
TChild child;
|
|
T* childAsT = &child;
|
|
{
|
|
Result<T*, int> result(&child);
|
|
TestSuccess(&result, childAsT);
|
|
}
|
|
{
|
|
Result<TChild*, int> resultChild(&child);
|
|
Result<T*, int> result(std::move(resultChild));
|
|
TestSuccess(&result, childAsT);
|
|
}
|
|
{
|
|
Result<TChild*, int> resultChild(&child);
|
|
Result<T*, int> result = std::move(resultChild);
|
|
TestSuccess(&result, childAsT);
|
|
}
|
|
}
|
|
|
|
// Result<const T*, E>
|
|
|
|
// Test constructing an error Result<const T*, E>
|
|
TEST(ResultBothPointerWithConstResult, ConstructingError) {
|
|
Result<const float*, int> result(std::make_unique<int>(dummyError));
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test moving an error Result<const T*, E>
|
|
TEST(ResultBothPointerWithConstResult, MovingError) {
|
|
Result<const float*, int> result(std::make_unique<int>(dummyError));
|
|
Result<const float*, int> movedResult(std::move(result));
|
|
TestError(&movedResult, dummyError);
|
|
}
|
|
|
|
// Test returning an error Result<const T*, E*>
|
|
TEST(ResultBothPointerWithConstResult, ReturningError) {
|
|
auto CreateError = []() -> Result<const float*, int> {
|
|
return {std::make_unique<int>(dummyError)};
|
|
};
|
|
|
|
Result<const float*, int> result = CreateError();
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test constructing a success Result<const T*, E*>
|
|
TEST(ResultBothPointerWithConstResult, ConstructingSuccess) {
|
|
Result<const float*, int> result(&dummyConstSuccess);
|
|
TestSuccess(&result, &dummyConstSuccess);
|
|
}
|
|
|
|
// Test moving a success Result<const T*, E*>
|
|
TEST(ResultBothPointerWithConstResult, MovingSuccess) {
|
|
Result<const float*, int> result(&dummyConstSuccess);
|
|
Result<const float*, int> movedResult(std::move(result));
|
|
TestSuccess(&movedResult, &dummyConstSuccess);
|
|
}
|
|
|
|
// Test returning a success Result<const T*, E*>
|
|
TEST(ResultBothPointerWithConstResult, ReturningSuccess) {
|
|
auto CreateSuccess = []() -> Result<const float*, int> { return {&dummyConstSuccess}; };
|
|
|
|
Result<const float*, int> result = CreateSuccess();
|
|
TestSuccess(&result, &dummyConstSuccess);
|
|
}
|
|
|
|
// Result<Ref<T>, E>
|
|
|
|
// Test constructing an error Result<Ref<T>, E>
|
|
TEST(ResultRefT, ConstructingError) {
|
|
Result<Ref<AClass>, int> result(std::make_unique<int>(dummyError));
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test moving an error Result<Ref<T>, E>
|
|
TEST(ResultRefT, MovingError) {
|
|
Result<Ref<AClass>, int> result(std::make_unique<int>(dummyError));
|
|
Result<Ref<AClass>, int> movedResult(std::move(result));
|
|
TestError(&movedResult, dummyError);
|
|
}
|
|
|
|
// Test returning an error Result<Ref<T>, E>
|
|
TEST(ResultRefT, ReturningError) {
|
|
auto CreateError = []() -> Result<Ref<AClass>, int> {
|
|
return {std::make_unique<int>(dummyError)};
|
|
};
|
|
|
|
Result<Ref<AClass>, int> result = CreateError();
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test constructing a success Result<Ref<T>, E>
|
|
TEST(ResultRefT, ConstructingSuccess) {
|
|
AClass success;
|
|
|
|
Ref<AClass> refObj(&success);
|
|
Result<Ref<AClass>, int> result(std::move(refObj));
|
|
TestSuccess(&result, &success);
|
|
}
|
|
|
|
// Test moving a success Result<Ref<T>, E>
|
|
TEST(ResultRefT, MovingSuccess) {
|
|
AClass success;
|
|
|
|
Ref<AClass> refObj(&success);
|
|
Result<Ref<AClass>, int> result(std::move(refObj));
|
|
Result<Ref<AClass>, int> movedResult(std::move(result));
|
|
TestSuccess(&movedResult, &success);
|
|
}
|
|
|
|
// Test returning a success Result<Ref<T>, E>
|
|
TEST(ResultRefT, ReturningSuccess) {
|
|
AClass success;
|
|
auto CreateSuccess = [&success]() -> Result<Ref<AClass>, int> {
|
|
return Ref<AClass>(&success);
|
|
};
|
|
|
|
Result<Ref<AClass>, int> result = CreateSuccess();
|
|
TestSuccess(&result, &success);
|
|
}
|
|
|
|
class OtherClass {
|
|
public:
|
|
int a = 0;
|
|
};
|
|
class Base : public RefCounted {};
|
|
class Child : public OtherClass, public Base {};
|
|
|
|
// Test constructing a Result<Ref<TChild>, E>
|
|
TEST(ResultRefT, ConversionFromChildConstructor) {
|
|
Child child;
|
|
Ref<Child> refChild(&child);
|
|
|
|
Result<Ref<Base>, int> result(std::move(refChild));
|
|
TestSuccess<Base>(&result, &child);
|
|
}
|
|
|
|
// Test copy constructing Result<Ref<TChild>, E>
|
|
TEST(ResultRefT, ConversionFromChildCopyConstructor) {
|
|
Child child;
|
|
Ref<Child> refChild(&child);
|
|
|
|
Result<Ref<Child>, int> resultChild(std::move(refChild));
|
|
Result<Ref<Base>, int> result(std::move(resultChild));
|
|
TestSuccess<Base>(&result, &child);
|
|
}
|
|
|
|
// Test assignment operator for Result<Ref<TChild>, E>
|
|
TEST(ResultRefT, ConversionFromChildAssignmentOperator) {
|
|
Child child;
|
|
Ref<Child> refChild(&child);
|
|
|
|
Result<Ref<Child>, int> resultChild(std::move(refChild));
|
|
Result<Ref<Base>, int> result = std::move(resultChild);
|
|
TestSuccess<Base>(&result, &child);
|
|
}
|
|
|
|
// Result<T, E>
|
|
|
|
// Test constructing an error Result<T, E>
|
|
TEST(ResultGeneric, ConstructingError) {
|
|
Result<std::vector<float>, int> result(std::make_unique<int>(dummyError));
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test moving an error Result<T, E>
|
|
TEST(ResultGeneric, MovingError) {
|
|
Result<std::vector<float>, int> result(std::make_unique<int>(dummyError));
|
|
Result<std::vector<float>, int> movedResult(std::move(result));
|
|
TestError(&movedResult, dummyError);
|
|
}
|
|
|
|
// Test returning an error Result<T, E>
|
|
TEST(ResultGeneric, ReturningError) {
|
|
auto CreateError = []() -> Result<std::vector<float>, int> {
|
|
return {std::make_unique<int>(dummyError)};
|
|
};
|
|
|
|
Result<std::vector<float>, int> result = CreateError();
|
|
TestError(&result, dummyError);
|
|
}
|
|
|
|
// Test constructing a success Result<T, E>
|
|
TEST(ResultGeneric, ConstructingSuccess) {
|
|
Result<std::vector<float>, int> result({1.0f});
|
|
TestSuccess(&result, {1.0f});
|
|
}
|
|
|
|
// Test moving a success Result<T, E>
|
|
TEST(ResultGeneric, MovingSuccess) {
|
|
Result<std::vector<float>, int> result({1.0f});
|
|
Result<std::vector<float>, int> movedResult(std::move(result));
|
|
TestSuccess(&movedResult, {1.0f});
|
|
}
|
|
|
|
// Test returning a success Result<T, E>
|
|
TEST(ResultGeneric, ReturningSuccess) {
|
|
auto CreateSuccess = []() -> Result<std::vector<float>, int> { return {{1.0f}}; };
|
|
|
|
Result<std::vector<float>, int> result = CreateSuccess();
|
|
TestSuccess(&result, {1.0f});
|
|
}
|
|
|
|
} // anonymous namespace
|