Write tests for the move semantics.

Change-Id: Ie3acd1e714b7536e2c92b51e80653eec824bd7bd
Reviewed-on: https://code-review.googlesource.com/c/re2/+/57432
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/testing/filtered_re2_test.cc b/re2/testing/filtered_re2_test.cc
index deef2f8..c788fda 100644
--- a/re2/testing/filtered_re2_test.cc
+++ b/re2/testing/filtered_re2_test.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 #include <vector>
+#include <utility>
 
 #include "util/test.h"
 #include "util/logging.h"
@@ -291,4 +292,49 @@
                                  "EmptyStringInStringSetBug", &v));
 }
 
+TEST(FilteredRE2Test, MoveSemantics) {
+  FilterTestVars v1;
+  int id;
+  v1.f.Add("foo\\d+", v1.opts, &id);
+  EXPECT_EQ(0, id);
+  v1.f.Compile(&v1.atoms);
+  EXPECT_EQ(1, v1.atoms.size());
+  EXPECT_EQ("foo", v1.atoms[0]);
+  v1.f.AllMatches("abc foo1 xyz", {0}, &v1.matches);
+  EXPECT_EQ(1, v1.matches.size());
+  EXPECT_EQ(0, v1.matches[0]);
+  v1.f.AllMatches("abc bar2 xyz", {0}, &v1.matches);
+  EXPECT_EQ(0, v1.matches.size());
+
+  // The moved-to object should do what the moved-from object did.
+  FilterTestVars v2;
+  v2.f = std::move(v1.f);
+  v2.f.AllMatches("abc foo1 xyz", {0}, &v2.matches);
+  EXPECT_EQ(1, v2.matches.size());
+  EXPECT_EQ(0, v2.matches[0]);
+  v2.f.AllMatches("abc bar2 xyz", {0}, &v2.matches);
+  EXPECT_EQ(0, v2.matches.size());
+
+  // The moved-from object should have been reset and be reusable.
+  v1.f.Add("bar\\d+", v1.opts, &id);
+  EXPECT_EQ(0, id);
+  v1.f.Compile(&v1.atoms);
+  EXPECT_EQ(1, v1.atoms.size());
+  EXPECT_EQ("bar", v1.atoms[0]);
+  v1.f.AllMatches("abc foo1 xyz", {0}, &v1.matches);
+  EXPECT_EQ(0, v1.matches.size());
+  v1.f.AllMatches("abc bar2 xyz", {0}, &v1.matches);
+  EXPECT_EQ(1, v1.matches.size());
+  EXPECT_EQ(0, v1.matches[0]);
+
+  // Verify that "overwriting" works and also doesn't leak memory.
+  // (The latter will need a leak detector such as LeakSanitizer.)
+  v1.f = std::move(v2.f);
+  v1.f.AllMatches("abc foo1 xyz", {0}, &v1.matches);
+  EXPECT_EQ(1, v1.matches.size());
+  EXPECT_EQ(0, v1.matches[0]);
+  v1.f.AllMatches("abc bar2 xyz", {0}, &v1.matches);
+  EXPECT_EQ(0, v1.matches.size());
+}
+
 }  //  namespace re2
diff --git a/re2/testing/set_test.cc b/re2/testing/set_test.cc
index 61d1cf2..5a760c4 100644
--- a/re2/testing/set_test.cc
+++ b/re2/testing/set_test.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 #include <string>
 #include <vector>
+#include <utility>
 
 #include "util/test.h"
 #include "util/logging.h"
@@ -201,4 +202,29 @@
   ASSERT_EQ(v[0], 0);
 }
 
+TEST(Set, MoveSemantics) {
+  RE2::Set s1(RE2::DefaultOptions, RE2::UNANCHORED);
+  ASSERT_EQ(s1.Add("foo\\d+", NULL), 0);
+  ASSERT_EQ(s1.Compile(), true);
+  ASSERT_EQ(s1.Match("abc foo1 xyz", NULL), true);
+  ASSERT_EQ(s1.Match("abc bar2 xyz", NULL), false);
+
+  // The moved-to object should do what the moved-from object did.
+  RE2::Set s2 = std::move(s1);
+  ASSERT_EQ(s2.Match("abc foo1 xyz", NULL), true);
+  ASSERT_EQ(s2.Match("abc bar2 xyz", NULL), false);
+
+  // The moved-from object should have been reset and be reusable.
+  ASSERT_EQ(s1.Add("bar\\d+", NULL), 0);
+  ASSERT_EQ(s1.Compile(), true);
+  ASSERT_EQ(s1.Match("abc foo1 xyz", NULL), false);
+  ASSERT_EQ(s1.Match("abc bar2 xyz", NULL), true);
+
+  // Verify that "overwriting" works and also doesn't leak memory.
+  // (The latter will need a leak detector such as LeakSanitizer.)
+  s1 = std::move(s2);
+  ASSERT_EQ(s1.Match("abc foo1 xyz", NULL), true);
+  ASSERT_EQ(s1.Match("abc bar2 xyz", NULL), false);
+}
+
 }  // namespace re2