forked from vitessio/vitess
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vschema.go
174 lines (154 loc) · 4.28 KB
/
vschema.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package test
import (
"strings"
"testing"
"github.com/youtube/vitess/go/vt/topo"
"golang.org/x/net/context"
topodatapb "github.com/youtube/vitess/go/vt/proto/topodata"
)
// CheckVSchema runs the tests on the VSchema part of the API
func CheckVSchema(ctx context.Context, t *testing.T, ts topo.Impl) {
if err := ts.CreateKeyspace(ctx, "test_keyspace", &topodatapb.Keyspace{}); err != nil {
t.Fatalf("CreateKeyspace: %v", err)
}
shard := &topodatapb.Shard{
KeyRange: newKeyRange("b0-c0"),
}
if err := ts.CreateShard(ctx, "test_keyspace", "b0-c0", shard); err != nil {
t.Fatalf("CreateShard: %v", err)
}
got, err := ts.GetVSchema(ctx, "test_keyspace")
if err != nil {
t.Error(err)
}
want := "{}"
if got != want {
t.Errorf("GetVSchema: %s, want %s", got, want)
}
err = ts.SaveVSchema(ctx, "test_keyspace", `{ "Sharded": true }`)
if err != nil {
t.Error(err)
}
got, err = ts.GetVSchema(ctx, "test_keyspace")
if err != nil {
t.Error(err)
}
want = `{ "Sharded": true }`
if got != want {
t.Errorf("GetVSchema: %s, want %s", got, want)
}
err = ts.SaveVSchema(ctx, "test_keyspace", `{ "Sharded": false }`)
if err != nil {
t.Error(err)
}
got, err = ts.GetVSchema(ctx, "test_keyspace")
if err != nil {
t.Error(err)
}
want = `{ "Sharded": false }`
if got != want {
t.Errorf("GetVSchema: %s, want %s", got, want)
}
tts := topo.Server{Impl: ts}
err = tts.SaveVSchema(ctx, "test_keyspace", "invalid")
want = "Unmarshal failed:"
if err == nil || !strings.HasPrefix(err.Error(), want) {
t.Errorf("SaveVSchema: %v, must start with %s", err, want)
}
// Make sure the vschema is not returned as a shard name,
// because they share the same directory location.
shards, err := ts.GetShardNames(ctx, "test_keyspace")
if err != nil {
t.Errorf("GetShardNames: %v", err)
}
if len(shards) != 1 || shards[0] != "b0-c0" {
t.Errorf(`GetShardNames: want [ "b0-c0" ], got %v`, shards)
}
}
// CheckWatchVSchema makes sure WatchVSchema works as expected
func CheckWatchVSchema(ctx context.Context, t *testing.T, ts topo.Impl) {
keyspace := "test_keyspace"
// start watching, should get nil first
ctx, cancel := context.WithCancel(ctx)
notifications, err := ts.WatchVSchema(ctx, keyspace)
if err != nil {
t.Fatalf("WatchVSchema failed: %v", err)
}
vs, ok := <-notifications
if !ok || vs != "{}" {
t.Fatalf("first value is wrong: %v %v", vs, ok)
}
// update the VSchema, should get a notification
newContents := `{ "Sharded": false }`
if err := ts.SaveVSchema(ctx, keyspace, newContents); err != nil {
t.Fatalf("SaveVSchema failed: %v", err)
}
for {
vs, ok := <-notifications
if !ok {
t.Fatalf("watch channel is closed???")
}
if vs == "{}" {
// duplicate notification of the first value, that's OK
continue
}
// non-empty value, that one should be ours
if vs != newContents {
t.Fatalf("first value is wrong: got %v expected %v", vs, newContents)
}
break
}
// empty the VSchema, should get a notification
if err := ts.SaveVSchema(ctx, keyspace, "{}"); err != nil {
t.Fatalf("SaveVSchema failed: %v", err)
}
for {
vs, ok := <-notifications
if !ok {
t.Fatalf("watch channel is closed???")
}
if vs == "{}" {
break
}
// duplicate notification of the first value, that's OK,
// but value better be good.
if vs != newContents {
t.Fatalf("duplicate notification value is bad: %v", vs)
}
}
// re-create the value, a bit different, should get a notification
newContents = `{ "Sharded": true }`
if err := ts.SaveVSchema(ctx, keyspace, newContents); err != nil {
t.Fatalf("SaveVSchema failed: %v", err)
}
for {
vs, ok := <-notifications
if !ok {
t.Fatalf("watch channel is closed???")
}
if vs == "{}" {
// duplicate notification of the closed value, that's OK
continue
}
// non-empty value, that one should be ours
if vs != newContents {
t.Fatalf("value after delete / re-create is wrong: %v", vs)
}
break
}
// close the context, should eventually get a closed
// notifications channel too
cancel()
for {
vs, ok := <-notifications
if !ok {
break
}
if vs != newContents {
t.Fatalf("duplicate notification value is bad: %v", vs)
}
}
}