-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
Copy pathunwrap_validation_test.go
128 lines (118 loc) · 3.92 KB
/
unwrap_validation_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2020 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package catalogkv
import (
"context"
"encoding/hex"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"testing"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/kv"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/sql/catalog"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
"github.com/cockroachdb/cockroach/pkg/testutils"
"github.com/cockroachdb/cockroach/pkg/util/encoding/csv"
"github.com/cockroachdb/cockroach/pkg/util/hlc"
"github.com/cockroachdb/cockroach/pkg/util/protoutil"
"github.com/cockroachdb/errors"
"github.com/stretchr/testify/require"
)
// TestUnwrapValidation uses testdata to find issues validating descriptors.
// The test is driven by serialized testdata. The expected testdata directories
// will hold a file "descriptors.csv" which is a csv of id,descriptor where
// descriptor is hex encoded.
func TestUnwrapValidation(t *testing.T) {
testdata := testutils.TestDataPath("testdata", "unwrap_validation")
const descriptorsCSVFilename = "descriptors.csv"
dirs, err := ioutil.ReadDir(testdata)
require.NoError(t, err)
for _, dir := range dirs {
if !dir.IsDir() {
continue
}
dp := filepath.Join(testdata, dir.Name(), descriptorsCSVFilename)
if _, err := os.Stat(dp); errors.Is(err, os.ErrNotExist) {
continue
}
t.Run(dir.Name(), func(t *testing.T) {
unwrapValidationTest(t, dp)
})
}
}
func unwrapValidationTest(t *testing.T, descriptorCSVPath string) {
m := decodeDescriptorDSV(t, descriptorCSVPath)
for id, data := range m {
var descProto descpb.Descriptor
require.NoError(t, protoutil.Unmarshal(data, &descProto))
desc, err := m.GetDesc(context.Background(), id)
require.NoErrorf(t, err, "id: %d", id)
require.NotNil(t, desc, "id: %d", id)
err = catalog.ValidateSelfAndCrossReferences(context.Background(), m, desc)
require.NoErrorf(t, err, "id: %d", id)
}
}
// oneLevelMapDescGetter exists to mirror the behavior of the
// oneLevelTxnDescGetter but instead of reading from the key-value store, it
// reads from the map.
type oneLevelMapDescGetter map[descpb.ID][]byte
var _ catalog.DescGetter = (oneLevelMapDescGetter)(nil)
func (o oneLevelMapDescGetter) GetDesc(
ctx context.Context, id descpb.ID,
) (catalog.Descriptor, error) {
var desc descpb.Descriptor
if err := protoutil.Unmarshal(o[id], &desc); err != nil {
return nil, err
}
mt := descpb.GetDescriptorModificationTime(&desc)
if mt == (hlc.Timestamp{}) {
mt = hlc.Timestamp{WallTime: 1}
}
v := roachpb.Value{Timestamp: mt}
if err := v.SetProto(&desc); err != nil {
return nil, err
}
return descriptorFromKeyValue(
ctx,
keys.SQLCodec{}, // dummy value, not used due to passing Any and bestEffort.
kv.KeyValue{Value: &v},
immutable,
catalog.Any,
bestEffort,
nil, /* dg */ // See oneLevelUncachedDescGetter.fromKeyValuePair().
catalog.ValidationLevelSelfOnly,
)
}
func decodeDescriptorDSV(t *testing.T, descriptorCSVPath string) oneLevelMapDescGetter {
f, err := os.Open(descriptorCSVPath)
require.NoError(t, err)
defer f.Close()
r := csv.NewReader(f)
records, err := r.ReadAll()
require.NoError(t, err)
require.Equal(t, records[0], []string{"id", "descriptor"})
records = records[1:]
m := decodeCSVRecordsToDescGetter(t, records)
return m
}
func decodeCSVRecordsToDescGetter(t *testing.T, records [][]string) oneLevelMapDescGetter {
m := oneLevelMapDescGetter{}
for _, rec := range records {
id, err := strconv.Atoi(rec[0])
require.NoError(t, err)
decoded, err := hex.DecodeString(rec[1])
require.NoError(t, err)
m[descpb.ID(id)] = decoded
}
return m
}