Backfill unittests for fxcrt::Spancpy() and Spanset()

In particular, test that we can do zero-length copies so as to avoid
requiring an if (!span.empty()) before copies as code is updated. Note
that to avoid memcpy(0,0,0)'s undefined behaviour, we make empty spans
by taking exhaustive sub-spans rather than using {}.

Change-Id: I84bbe31d7757a6f1a41ad246a0544afeb6890663
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/82730
Auto-Submit: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index 6b20ced..30c3a71 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -160,6 +160,7 @@
     "retained_tree_node_unittest.cpp",
     "scoped_set_insertion_unittest.cpp",
     "shared_copy_on_write_unittest.cpp",
+    "span_util_unittest.cpp",
     "string_pool_template_unittest.cpp",
     "tree_node_unittest.cpp",
     "unowned_ptr_unittest.cpp",
diff --git a/core/fxcrt/span_util_unittest.cpp b/core/fxcrt/span_util_unittest.cpp
new file mode 100644
index 0000000..d0de999
--- /dev/null
+++ b/core/fxcrt/span_util_unittest.cpp
@@ -0,0 +1,67 @@
+// Copyright 2021 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/span_util.h"
+
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(Spanset, Fits) {
+  std::vector<char> dst(4, 'B');
+  fxcrt::spanset(pdfium::make_span(dst).first(2), 'A');
+  EXPECT_EQ(dst[0], 'A');
+  EXPECT_EQ(dst[1], 'A');
+  EXPECT_EQ(dst[2], 'B');
+  EXPECT_EQ(dst[3], 'B');
+}
+
+TEST(Spanset, Empty) {
+  std::vector<char> dst(4, 'B');
+  fxcrt::spanset(fxcrt::Subspan(dst, 4), 'A');
+  EXPECT_EQ(dst[0], 'B');
+  EXPECT_EQ(dst[1], 'B');
+  EXPECT_EQ(dst[2], 'B');
+  EXPECT_EQ(dst[3], 'B');
+}
+
+TEST(Spancpy, FitsEntirely) {
+  std::vector<char> src(4, 'A');
+  std::vector<char> dst(4, 'B');
+  fxcrt::spancpy(pdfium::make_span(dst), pdfium::make_span(src));
+  EXPECT_EQ(dst[0], 'A');
+  EXPECT_EQ(dst[1], 'A');
+  EXPECT_EQ(dst[2], 'A');
+  EXPECT_EQ(dst[3], 'A');
+}
+
+TEST(Spancpy, FitsWithin) {
+  std::vector<char> src(2, 'A');
+  std::vector<char> dst(4, 'B');
+  fxcrt::spancpy(fxcrt::Subspan(dst, 1), pdfium::make_span(src));
+  EXPECT_EQ(dst[0], 'B');
+  EXPECT_EQ(dst[1], 'A');
+  EXPECT_EQ(dst[2], 'A');
+  EXPECT_EQ(dst[3], 'B');
+}
+
+TEST(Spancpy, EmptyCopyWithin) {
+  std::vector<char> src(2, 'A');
+  std::vector<char> dst(4, 'B');
+  fxcrt::spancpy(fxcrt::Subspan(dst, 1), fxcrt::Subspan(src, 2));
+  EXPECT_EQ(dst[0], 'B');
+  EXPECT_EQ(dst[1], 'B');
+  EXPECT_EQ(dst[2], 'B');
+  EXPECT_EQ(dst[3], 'B');
+}
+
+TEST(Spancpy, EmptyCopyToEmpty) {
+  std::vector<char> src(2, 'A');
+  std::vector<char> dst(4, 'B');
+  fxcrt::spancpy(fxcrt::Subspan(dst, 4), fxcrt::Subspan(src, 2));
+  EXPECT_EQ(dst[0], 'B');
+  EXPECT_EQ(dst[1], 'B');
+  EXPECT_EQ(dst[2], 'B');
+  EXPECT_EQ(dst[3], 'B');
+}