Add dawn_native unittests for Limits

Adds some unittests for Limits to dawn_unittests.
Statically links dawn_unittests against dawn_native
to access the internals. Additional tests for dawn_native
can now be added to dawn_unittests as well.

Bug: dawn:685, dawn:1105
Change-Id: I1e67c2f673e43d0e07693f3a50920129f135440e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/64780
Reviewed-by: Brandon Jones <bajones@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index 82d40dd..ce27136 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -135,8 +135,8 @@
     "${dawn_root}/src/common",
     "${dawn_root}/src/dawn:dawn_proc",
     "${dawn_root}/src/dawn:dawncpp",
-    "${dawn_root}/src/dawn_native",
     "${dawn_root}/src/dawn_native:dawn_native_sources",
+    "${dawn_root}/src/dawn_native:dawn_native_static",
     "${dawn_root}/src/dawn_wire",
     "${dawn_root}/src/utils:dawn_utils",
   ]
@@ -169,6 +169,7 @@
     "unittests/ITypBitsetTests.cpp",
     "unittests/ITypSpanTests.cpp",
     "unittests/ITypVectorTests.cpp",
+    "unittests/LimitsTests.cpp",
     "unittests/LinkedListTests.cpp",
     "unittests/MathTests.cpp",
     "unittests/ObjectBaseTests.cpp",
diff --git a/src/tests/unittests/LimitsTests.cpp b/src/tests/unittests/LimitsTests.cpp
new file mode 100644
index 0000000..b8b403e
--- /dev/null
+++ b/src/tests/unittests/LimitsTests.cpp
@@ -0,0 +1,112 @@
+// 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 <gtest/gtest.h>
+
+#include "dawn_native/Limits.h"
+
+// Test |GetDefaultLimits| returns the default.
+TEST(Limits, GetDefaultLimits) {
+    dawn_native::Limits limits = {};
+    EXPECT_NE(limits.maxBindGroups, 4u);
+
+    dawn_native::GetDefaultLimits(&limits);
+
+    EXPECT_EQ(limits.maxBindGroups, 4u);
+}
+
+// Test |ReifyDefaultLimits| populates the default if
+// values are undefined.
+TEST(Limits, ReifyDefaultLimits_PopulatesDefault) {
+    dawn_native::Limits limits;
+    limits.maxComputeWorkgroupStorageSize = wgpu::kLimitU32Undefined;
+    limits.maxStorageBufferBindingSize = wgpu::kLimitU64Undefined;
+
+    dawn_native::Limits reified = dawn_native::ReifyDefaultLimits(limits);
+    EXPECT_EQ(reified.maxComputeWorkgroupStorageSize, 16352u);
+    EXPECT_EQ(reified.maxStorageBufferBindingSize, 134217728ul);
+}
+
+// Test |ReifyDefaultLimits| clamps to the default if
+// values are worse than the default.
+TEST(Limits, ReifyDefaultLimits_Clamps) {
+    dawn_native::Limits limits;
+    limits.maxStorageBuffersPerShaderStage = 4;
+    limits.minUniformBufferOffsetAlignment = 512;
+
+    dawn_native::Limits reified = dawn_native::ReifyDefaultLimits(limits);
+    EXPECT_EQ(reified.maxStorageBuffersPerShaderStage, 8u);
+    EXPECT_EQ(reified.minUniformBufferOffsetAlignment, 256u);
+}
+
+// Test |ValidateLimits| works to validate limits are not better
+// than supported.
+TEST(Limits, ValidateLimits) {
+    // Start with the default for supported.
+    dawn_native::Limits defaults;
+    dawn_native::GetDefaultLimits(&defaults);
+
+    // Test supported == required is valid.
+    {
+        dawn_native::Limits required = defaults;
+        EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess());
+    }
+
+    // Test supported == required is valid, when they are not default.
+    {
+        dawn_native::Limits supported = defaults;
+        dawn_native::Limits required = defaults;
+        supported.maxBindGroups += 1;
+        required.maxBindGroups += 1;
+        EXPECT_TRUE(ValidateLimits(supported, required).IsSuccess());
+    }
+
+    // Test that default-initialized (all undefined) is valid.
+    {
+        dawn_native::Limits required = {};
+        EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess());
+    }
+
+    // Test that better than max is invalid.
+    {
+        dawn_native::Limits required = {};
+        required.maxTextureDimension3D = defaults.maxTextureDimension3D + 1;
+        dawn_native::MaybeError err = ValidateLimits(defaults, required);
+        EXPECT_TRUE(err.IsError());
+        err.AcquireError();
+    }
+
+    // Test that worse than max is valid.
+    {
+        dawn_native::Limits required = {};
+        required.maxComputeWorkgroupSizeX = defaults.maxComputeWorkgroupSizeX - 1;
+        EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess());
+    }
+
+    // Test that better than min is invalid.
+    {
+        dawn_native::Limits required = {};
+        required.minUniformBufferOffsetAlignment = defaults.minUniformBufferOffsetAlignment / 2;
+        dawn_native::MaybeError err = ValidateLimits(defaults, required);
+        EXPECT_TRUE(err.IsError());
+        err.AcquireError();
+    }
+
+    // Test that worse than min is valid.
+    {
+        dawn_native::Limits required = {};
+        required.minStorageBufferOffsetAlignment = defaults.minStorageBufferOffsetAlignment * 2;
+        EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess());
+    }
+}