From: Shengjing Zhu <zhsj@debian.org>
Date: Sat, 29 Oct 2022 18:47:30 +0800
Subject: Backport testEqual in spanner package

Change in transaction_test.go
  https://github.com/googleapis/google-cloud-go/commit/91ceec29
Change in cmp_test.go
  Copy from https://github.com/googleapis/google-cloud-go/blob/main/spanner/cmp_test.go
  There are several commits, so just copy the latest.
---
 spanner/cmp_test.go         | 42 +++++++++++++++++++++++++++++++++++++++++-
 spanner/transaction_test.go | 14 +-------------
 2 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/spanner/cmp_test.go b/spanner/cmp_test.go
index 0e94edc..374fb82 100644
--- a/spanner/cmp_test.go
+++ b/spanner/cmp_test.go
@@ -17,6 +17,9 @@ limitations under the License.
 package spanner
 
 import (
+	"math/big"
+	"strings"
+
 	"cloud.google.com/go/internal/testutil"
 	"github.com/google/go-cmp/cmp"
 )
@@ -25,5 +28,42 @@ import (
 func testEqual(a, b interface{}) bool {
 	return testutil.Equal(a, b,
 		cmp.AllowUnexported(TimestampBound{}, Error{}, TransactionOutcomeUnknownError{},
-			Mutation{}, Row{}, Partition{}, BatchReadOnlyTransactionID{}))
+			Mutation{}, Row{}, Partition{}, BatchReadOnlyTransactionID{}, big.Rat{}, big.Int{}),
+		cmp.FilterPath(func(path cmp.Path) bool {
+			// Ignore Error.state, Error.sizeCache, and Error.unknownFields
+			if strings.HasSuffix(path.GoString(), ".err.(*status.Error).state") {
+				return true
+			}
+			if strings.HasSuffix(path.GoString(), ".err.(*status.Error).sizeCache") {
+				return true
+			}
+			if strings.HasSuffix(path.GoString(), ".err.(*status.Error).unknownFields") {
+				return true
+			}
+			if strings.HasSuffix(path.GoString(), ".err.(*status.Error).e") {
+				return true
+			}
+			if strings.Contains(path.GoString(), "{*status.Error}.state") {
+				return true
+			}
+			if strings.Contains(path.GoString(), "{*status.Error}.sizeCache") {
+				return true
+			}
+			if strings.Contains(path.GoString(), "{*status.Error}.unknownFields") {
+				return true
+			}
+			if strings.Contains(path.GoString(), "{*status.Error}.e") {
+				return true
+			}
+			if strings.Contains(path.GoString(), "{*status.Error}.s") {
+				return true
+			}
+			if strings.Contains(path.GoString(), "(*status.Error).s") {
+				return true
+			}
+			if strings.Contains(path.GoString(), "{*spanner.Error}.err") {
+				return true
+			}
+			return false
+		}, cmp.Ignore()))
 }
diff --git a/spanner/transaction_test.go b/spanner/transaction_test.go
index 8a09d29..9f7733b 100644
--- a/spanner/transaction_test.go
+++ b/spanner/transaction_test.go
@@ -21,14 +21,12 @@ import (
 	"errors"
 	"fmt"
 	"reflect"
-	"strings"
 	"sync"
 	"testing"
 	"time"
 
 	. "cloud.google.com/go/spanner/internal/testutil"
 	"github.com/golang/protobuf/ptypes"
-	"github.com/google/go-cmp/cmp"
 	"google.golang.org/genproto/googleapis/rpc/errdetails"
 	sppb "google.golang.org/genproto/googleapis/spanner/v1"
 	"google.golang.org/grpc/codes"
@@ -243,17 +241,7 @@ func TestTransaction_SessionNotFound(t *testing.T) {
 		Insert("Accounts", []string{"AccountId", "Nickname", "Balance"}, []interface{}{int64(2), "Bar", int64(1)}),
 	}
 	_, got := client.Apply(ctx, ms, ApplyAtLeastOnce())
-	if !cmp.Equal(wantErr, got,
-		cmp.AllowUnexported(Error{}), cmp.FilterPath(func(path cmp.Path) bool {
-			// Ignore statusError Details and Error.trailers.
-			if strings.Contains(path.GoString(), "{*spanner.Error}.err.(*status.statusError).Details") {
-				return true
-			}
-			if strings.Contains(path.GoString(), "{*spanner.Error}.trailers") {
-				return true
-			}
-			return false
-		}, cmp.Ignore())) {
+	if !testEqual(wantErr, got) {
 		t.Fatalf("Expect Apply to fail\nGot:  %v\nWant: %v\n", got, wantErr)
 	}
 }
