Add unittests for dawn::native::Blob
Bug: dawn:549 Change-Id: Ie3db7e8f1aa720c8513480688611cadd9b72647d Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/92600 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Shrek Shao <shrekshao@google.com> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
d527ffa3c0
commit
1a82cc9641
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "dawn/common/Assert.h"
|
||||
#include "dawn/native/Blob.h"
|
||||
|
||||
namespace dawn::native {
|
||||
|
@ -35,11 +36,24 @@ Blob Blob::UnsafeCreateWithDeleter(uint8_t* data, size_t size, std::function<voi
|
|||
Blob::Blob() : mData(nullptr), mSize(0), mDeleter({}) {}
|
||||
|
||||
Blob::Blob(uint8_t* data, size_t size, std::function<void()> deleter)
|
||||
: mData(data), mSize(size), mDeleter(std::move(deleter)) {}
|
||||
: mData(data), mSize(size), mDeleter(std::move(deleter)) {
|
||||
// It is invalid to make a blob that has null data unless its size is also zero.
|
||||
ASSERT(data != nullptr || size == 0);
|
||||
}
|
||||
|
||||
Blob::Blob(Blob&&) = default;
|
||||
Blob::Blob(Blob&& rhs) : mData(rhs.mData), mSize(rhs.mSize) {
|
||||
mDeleter = std::move(rhs.mDeleter);
|
||||
}
|
||||
|
||||
Blob& Blob::operator=(Blob&&) = default;
|
||||
Blob& Blob::operator=(Blob&& rhs) {
|
||||
mData = rhs.mData;
|
||||
mSize = rhs.mSize;
|
||||
if (mDeleter) {
|
||||
mDeleter();
|
||||
}
|
||||
mDeleter = std::move(rhs.mDeleter);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Blob::~Blob() {
|
||||
if (mDeleter) {
|
||||
|
|
|
@ -252,6 +252,7 @@ dawn_test("dawn_unittests") {
|
|||
"unittests/ToBackendTests.cpp",
|
||||
"unittests/TypedIntegerTests.cpp",
|
||||
"unittests/VersionTests.cpp",
|
||||
"unittests/native/BlobTests.cpp",
|
||||
"unittests/native/CacheKeyTests.cpp",
|
||||
"unittests/native/CommandBufferEncodingTests.cpp",
|
||||
"unittests/native/CreatePipelineAsyncTaskTests.cpp",
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
// Copyright 2022 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 <utility>
|
||||
|
||||
#include "dawn/native/Blob.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace dawn::native {
|
||||
|
||||
namespace {
|
||||
|
||||
// Test that a blob starts empty.
|
||||
TEST(BlobTests, DefaultEmpty) {
|
||||
Blob b;
|
||||
EXPECT_TRUE(b.Empty());
|
||||
EXPECT_EQ(b.Data(), nullptr);
|
||||
EXPECT_EQ(b.Size(), 0u);
|
||||
}
|
||||
|
||||
// Test that you can create a blob with a size in bytes and write/read its contents.
|
||||
TEST(BlobTests, SizedCreation) {
|
||||
Blob b = CreateBlob(10);
|
||||
EXPECT_FALSE(b.Empty());
|
||||
EXPECT_EQ(b.Size(), 10u);
|
||||
ASSERT_NE(b.Data(), nullptr);
|
||||
// We should be able to copy 10 bytes into the blob.
|
||||
char data[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
memcpy(b.Data(), data, sizeof(data));
|
||||
// And retrieve the exact contents back.
|
||||
EXPECT_EQ(memcmp(b.Data(), data, sizeof(data)), 0);
|
||||
}
|
||||
|
||||
// Test that you can create a zero-sized blob.
|
||||
TEST(BlobTests, EmptySizedCreation) {
|
||||
Blob b = CreateBlob(0);
|
||||
EXPECT_TRUE(b.Empty());
|
||||
EXPECT_EQ(b.Data(), nullptr);
|
||||
EXPECT_EQ(b.Size(), 0u);
|
||||
}
|
||||
|
||||
// Test that you can create a blob with UnsafeCreateWithDeleter, and the deleter is
|
||||
// called on destruction.
|
||||
TEST(BlobTests, UnsafeCreateWithDeleter) {
|
||||
unsigned char data[13] = "hello world!";
|
||||
testing::StrictMock<testing::MockFunction<void()>> mockDeleter;
|
||||
{
|
||||
// Make a blob with a mock deleter.
|
||||
Blob b = Blob::UnsafeCreateWithDeleter(data, sizeof(data), [&]() { mockDeleter.Call(); });
|
||||
// Check the contents.
|
||||
EXPECT_FALSE(b.Empty());
|
||||
EXPECT_EQ(b.Size(), sizeof(data));
|
||||
ASSERT_EQ(b.Data(), data);
|
||||
EXPECT_EQ(memcmp(b.Data(), data, sizeof(data)), 0);
|
||||
|
||||
// |b| is deleted when this scope exits.
|
||||
EXPECT_CALL(mockDeleter, Call());
|
||||
}
|
||||
}
|
||||
|
||||
// Test that you can create a blob with UnsafeCreateWithDeleter with zero size but non-null data.
|
||||
// The deleter is still called on destruction, and the blob is normalized to be empty.
|
||||
TEST(BlobTests, UnsafeCreateWithDeleterZeroSize) {
|
||||
unsigned char data[13] = "hello world!";
|
||||
testing::StrictMock<testing::MockFunction<void()>> mockDeleter;
|
||||
{
|
||||
// Make a blob with a mock deleter.
|
||||
Blob b = Blob::UnsafeCreateWithDeleter(data, 0, [&]() { mockDeleter.Call(); });
|
||||
// Check the contents.
|
||||
EXPECT_TRUE(b.Empty());
|
||||
EXPECT_EQ(b.Size(), 0u);
|
||||
// Data still points to the data.
|
||||
EXPECT_EQ(b.Data(), data);
|
||||
|
||||
// |b| is deleted when this scope exits.
|
||||
EXPECT_CALL(mockDeleter, Call());
|
||||
}
|
||||
}
|
||||
|
||||
// Test that you can create a blob with UnsafeCreateWithDeleter that points to nothing.
|
||||
// The deleter should still be called.
|
||||
TEST(BlobTests, UnsafeCreateWithDeleterEmpty) {
|
||||
testing::StrictMock<testing::MockFunction<void()>> mockDeleter;
|
||||
{
|
||||
// Make a blob with a mock deleter.
|
||||
Blob b = Blob::UnsafeCreateWithDeleter(nullptr, 0, [&]() { mockDeleter.Call(); });
|
||||
// Check the contents.
|
||||
EXPECT_TRUE(b.Empty());
|
||||
EXPECT_EQ(b.Size(), 0u);
|
||||
EXPECT_EQ(b.Data(), nullptr);
|
||||
|
||||
// |b| is deleted when this scope exits.
|
||||
EXPECT_CALL(mockDeleter, Call());
|
||||
}
|
||||
}
|
||||
|
||||
// Test that move construction moves the data from one blob into the new one.
|
||||
TEST(BlobTests, MoveConstruct) {
|
||||
// Create the blob.
|
||||
Blob b1 = CreateBlob(10);
|
||||
char data[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
memcpy(b1.Data(), data, sizeof(data));
|
||||
|
||||
// Move construct b2 from b1.
|
||||
Blob b2(std::move(b1));
|
||||
|
||||
// Data should be moved.
|
||||
EXPECT_FALSE(b2.Empty());
|
||||
EXPECT_EQ(b2.Size(), 10u);
|
||||
ASSERT_NE(b2.Data(), nullptr);
|
||||
EXPECT_EQ(memcmp(b2.Data(), data, sizeof(data)), 0);
|
||||
}
|
||||
|
||||
// Test that move assignment moves the data from one blob into another.
|
||||
TEST(BlobTests, MoveAssign) {
|
||||
// Create the blob.
|
||||
Blob b1 = CreateBlob(10);
|
||||
char data[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
memcpy(b1.Data(), data, sizeof(data));
|
||||
|
||||
// Move assign b2 from b1.
|
||||
Blob b2;
|
||||
b2 = std::move(b1);
|
||||
|
||||
// Data should be moved.
|
||||
EXPECT_FALSE(b2.Empty());
|
||||
EXPECT_EQ(b2.Size(), 10u);
|
||||
ASSERT_NE(b2.Data(), nullptr);
|
||||
EXPECT_EQ(memcmp(b2.Data(), data, sizeof(data)), 0);
|
||||
}
|
||||
|
||||
// Test that move assignment can replace the contents of the moved-to blob.
|
||||
TEST(BlobTests, MoveAssignOver) {
|
||||
// Create the blob.
|
||||
Blob b1 = CreateBlob(10);
|
||||
char data[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
memcpy(b1.Data(), data, sizeof(data));
|
||||
|
||||
// Create another blob with a mock deleter.
|
||||
testing::StrictMock<testing::MockFunction<void()>> mockDeleter;
|
||||
Blob b2 = Blob::UnsafeCreateWithDeleter(nullptr, 0, [&]() { mockDeleter.Call(); });
|
||||
|
||||
// Move b1 into b2, replacing b2's contents, and expect the deleter to be called.
|
||||
EXPECT_CALL(mockDeleter, Call());
|
||||
b2 = std::move(b1);
|
||||
|
||||
// Data should be moved.
|
||||
EXPECT_FALSE(b2.Empty());
|
||||
EXPECT_EQ(b2.Size(), 10u);
|
||||
ASSERT_NE(b2.Data(), nullptr);
|
||||
EXPECT_EQ(memcmp(b2.Data(), data, sizeof(data)), 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace dawn::native
|
Loading…
Reference in New Issue