github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/col/coldata/testutils.go (about) 1 // Copyright 2020 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package coldata 12 13 import ( 14 "bytes" 15 "fmt" 16 17 "github.com/cockroachdb/cockroach/pkg/col/typeconv" 18 "github.com/cockroachdb/cockroach/pkg/sql/types" 19 "github.com/stretchr/testify/require" 20 ) 21 22 // testingT is a private interface that mirrors the testing.TB methods used. 23 // testing.TB cannot be used directly since testing is an illegal import. 24 // TODO(asubiotto): Remove AssertEquivalentBatches' dependency on testing.TB by 25 // checking for equality and returning a diff string instead of operating on 26 // testing.TB. 27 type testingT interface { 28 Helper() 29 Errorf(format string, args ...interface{}) 30 Fatal(args ...interface{}) 31 Fatalf(format string, args ...interface{}) 32 FailNow() 33 } 34 35 // AssertEquivalentBatches is a testing function that asserts that expected and 36 // actual are equivalent. 37 func AssertEquivalentBatches(t testingT, expected, actual Batch) { 38 t.Helper() 39 40 if actual.Selection() != nil { 41 t.Fatal("violated invariant that batches have no selection vectors") 42 } 43 require.Equal(t, expected.Length(), actual.Length()) 44 if expected.Length() == 0 { 45 // The schema of a zero-length batch is undefined, so the rest of the check 46 // is not required. 47 return 48 } 49 require.Equal(t, expected.Width(), actual.Width()) 50 for colIdx := 0; colIdx < expected.Width(); colIdx++ { 51 // Verify equality of ColVecs (this includes nulls). Since the coldata.Vec 52 // backing array is always of coldata.BatchSize() due to the scratch batch 53 // that the converter keeps around, the coldata.Vec needs to be sliced to 54 // the first length elements to match on length, otherwise the check will 55 // fail. 56 expectedVec := expected.ColVec(colIdx) 57 actualVec := actual.ColVec(colIdx) 58 require.Equal(t, expectedVec.Type(), actualVec.Type()) 59 require.Equal( 60 t, 61 expectedVec.Nulls().Slice(0, expected.Length()), 62 actualVec.Nulls().Slice(0, actual.Length()), 63 ) 64 canonicalTypeFamily := expectedVec.CanonicalTypeFamily() 65 if canonicalTypeFamily == types.BytesFamily { 66 // Cannot use require.Equal for this type. 67 // TODO(asubiotto): Again, why not? 68 expectedBytes := expectedVec.Bytes().Window(0, expected.Length()) 69 resultBytes := actualVec.Bytes().Window(0, actual.Length()) 70 require.Equal(t, expectedBytes.Len(), resultBytes.Len()) 71 for i := 0; i < expectedBytes.Len(); i++ { 72 if !bytes.Equal(expectedBytes.Get(i), resultBytes.Get(i)) { 73 t.Fatalf("bytes mismatch at index %d:\nexpected:\n%sactual:\n%s", i, expectedBytes, resultBytes) 74 } 75 } 76 } else if canonicalTypeFamily == types.TimestampTZFamily { 77 // Cannot use require.Equal for this type. 78 // TODO(yuzefovich): Again, why not? 79 expectedTimestamp := expectedVec.Timestamp()[0:expected.Length()] 80 resultTimestamp := actualVec.Timestamp()[0:actual.Length()] 81 require.Equal(t, len(expectedTimestamp), len(resultTimestamp)) 82 for i := range expectedTimestamp { 83 if !expectedTimestamp[i].Equal(resultTimestamp[i]) { 84 t.Fatalf("Timestamp mismatch at index %d:\nexpected:\n%sactual:\n%s", i, expectedTimestamp[i], resultTimestamp[i]) 85 } 86 } 87 } else if canonicalTypeFamily == types.IntervalFamily { 88 // Cannot use require.Equal for this type. 89 // TODO(yuzefovich): Again, why not? 90 expectedInterval := expectedVec.Interval()[0:expected.Length()] 91 resultInterval := actualVec.Interval()[0:actual.Length()] 92 require.Equal(t, len(expectedInterval), len(resultInterval)) 93 for i := range expectedInterval { 94 if expectedInterval[i].Compare(resultInterval[i]) != 0 { 95 t.Fatalf("Interval mismatch at index %d:\nexpected:\n%sactual:\n%s", i, expectedInterval[i], resultInterval[i]) 96 } 97 } 98 } else if expectedVec.CanonicalTypeFamily() == typeconv.DatumVecCanonicalTypeFamily { 99 // Cannot use require.Equal for this type. 100 expectedDatum := expectedVec.Datum().Slice(0 /* start */, expected.Length()) 101 resultDatum := actualVec.Datum().Slice(0 /* start */, actual.Length()) 102 require.Equal(t, expectedDatum.Len(), resultDatum.Len()) 103 for i := 0; i < expectedDatum.Len(); i++ { 104 expected := expectedDatum.Get(i).(fmt.Stringer).String() 105 actual := resultDatum.Get(i).(fmt.Stringer).String() 106 if expected != actual { 107 t.Fatalf("Datum mismatch at index %d:\nexpected:\n%sactual:\n%s", i, expectedDatum.Get(i), resultDatum.Get(i)) 108 } 109 } 110 } else { 111 require.Equal( 112 t, 113 expectedVec.Window(0, expected.Length()), 114 actualVec.Window(0, actual.Length()), 115 ) 116 } 117 } 118 }