mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Mechanical: Move mock packages out of ./pkg
Mechanical execution of:
```
git mv ./pkg/mock/mockserver ./client/pkg/mock
git mv ./pkg/mock/{mockstorage,mockstore,mockwait} ./server/pkg/mock
```
The packages depend on etcd API / protos - so they are NOT etcd-dependencies.
In such situation thay should be placed in 'pkg' folder.
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package mockserver provides mock implementations for etcdserver's server interface.
|
||||
package mockserver
|
||||
@@ -1,188 +0,0 @@
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package mockserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// MockServer provides a mocked out grpc server of the etcdserver interface.
|
||||
type MockServer struct {
|
||||
ln net.Listener
|
||||
Network string
|
||||
Address string
|
||||
GrpcServer *grpc.Server
|
||||
}
|
||||
|
||||
func (ms *MockServer) ResolverAddress() resolver.Address {
|
||||
switch ms.Network {
|
||||
case "unix":
|
||||
return resolver.Address{Addr: fmt.Sprintf("unix://%s", ms.Address)}
|
||||
case "tcp":
|
||||
return resolver.Address{Addr: ms.Address}
|
||||
default:
|
||||
panic("illegal network type: " + ms.Network)
|
||||
}
|
||||
}
|
||||
|
||||
// MockServers provides a cluster of mocket out gprc servers of the etcdserver interface.
|
||||
type MockServers struct {
|
||||
mu sync.RWMutex
|
||||
Servers []*MockServer
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// StartMockServers creates the desired count of mock servers
|
||||
// and starts them.
|
||||
func StartMockServers(count int) (ms *MockServers, err error) {
|
||||
return StartMockServersOnNetwork(count, "tcp")
|
||||
}
|
||||
|
||||
// StartMockServersOnNetwork creates mock servers on either 'tcp' or 'unix' sockets.
|
||||
func StartMockServersOnNetwork(count int, network string) (ms *MockServers, err error) {
|
||||
switch network {
|
||||
case "tcp":
|
||||
return startMockServersTcp(count)
|
||||
case "unix":
|
||||
return startMockServersUnix(count)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported network type: %s", network)
|
||||
}
|
||||
}
|
||||
|
||||
func startMockServersTcp(count int) (ms *MockServers, err error) {
|
||||
addrs := make([]string, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
addrs = append(addrs, "localhost:0")
|
||||
}
|
||||
return startMockServers("tcp", addrs)
|
||||
}
|
||||
|
||||
func startMockServersUnix(count int) (ms *MockServers, err error) {
|
||||
dir := os.TempDir()
|
||||
addrs := make([]string, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
f, err := ioutil.TempFile(dir, "etcd-unix-so-")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to allocate temp file for unix socket: %v", err)
|
||||
}
|
||||
fn := f.Name()
|
||||
err = os.Remove(fn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to remove temp file before creating unix socket: %v", err)
|
||||
}
|
||||
addrs = append(addrs, fn)
|
||||
}
|
||||
return startMockServers("unix", addrs)
|
||||
}
|
||||
|
||||
func startMockServers(network string, addrs []string) (ms *MockServers, err error) {
|
||||
ms = &MockServers{
|
||||
Servers: make([]*MockServer, len(addrs)),
|
||||
wg: sync.WaitGroup{},
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
ms.Stop()
|
||||
}
|
||||
}()
|
||||
for idx, addr := range addrs {
|
||||
ln, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to listen %v", err)
|
||||
}
|
||||
ms.Servers[idx] = &MockServer{ln: ln, Network: network, Address: ln.Addr().String()}
|
||||
ms.StartAt(idx)
|
||||
}
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
// StartAt restarts mock server at given index.
|
||||
func (ms *MockServers) StartAt(idx int) (err error) {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
|
||||
if ms.Servers[idx].ln == nil {
|
||||
ms.Servers[idx].ln, err = net.Listen(ms.Servers[idx].Network, ms.Servers[idx].Address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
svr := grpc.NewServer()
|
||||
pb.RegisterKVServer(svr, &mockKVServer{})
|
||||
ms.Servers[idx].GrpcServer = svr
|
||||
|
||||
ms.wg.Add(1)
|
||||
go func(svr *grpc.Server, l net.Listener) {
|
||||
svr.Serve(l)
|
||||
}(ms.Servers[idx].GrpcServer, ms.Servers[idx].ln)
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopAt stops mock server at given index.
|
||||
func (ms *MockServers) StopAt(idx int) {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
|
||||
if ms.Servers[idx].ln == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ms.Servers[idx].GrpcServer.Stop()
|
||||
ms.Servers[idx].GrpcServer = nil
|
||||
ms.Servers[idx].ln = nil
|
||||
ms.wg.Done()
|
||||
}
|
||||
|
||||
// Stop stops the mock server, immediately closing all open connections and listeners.
|
||||
func (ms *MockServers) Stop() {
|
||||
for idx := range ms.Servers {
|
||||
ms.StopAt(idx)
|
||||
}
|
||||
ms.wg.Wait()
|
||||
}
|
||||
|
||||
type mockKVServer struct{}
|
||||
|
||||
func (m *mockKVServer) Range(context.Context, *pb.RangeRequest) (*pb.RangeResponse, error) {
|
||||
return &pb.RangeResponse{}, nil
|
||||
}
|
||||
|
||||
func (m *mockKVServer) Put(context.Context, *pb.PutRequest) (*pb.PutResponse, error) {
|
||||
return &pb.PutResponse{}, nil
|
||||
}
|
||||
|
||||
func (m *mockKVServer) DeleteRange(context.Context, *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
|
||||
return &pb.DeleteRangeResponse{}, nil
|
||||
}
|
||||
|
||||
func (m *mockKVServer) Txn(context.Context, *pb.TxnRequest) (*pb.TxnResponse, error) {
|
||||
return &pb.TxnResponse{}, nil
|
||||
}
|
||||
|
||||
func (m *mockKVServer) Compact(context.Context, *pb.CompactionRequest) (*pb.CompactionResponse, error) {
|
||||
return &pb.CompactionResponse{}, nil
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package mockstorage provides mock implementations for etcdserver's storage interface.
|
||||
package mockstorage
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package mockstorage
|
||||
|
||||
import (
|
||||
"go.etcd.io/etcd/v3/pkg/testutil"
|
||||
"go.etcd.io/etcd/v3/raft"
|
||||
"go.etcd.io/etcd/v3/raft/raftpb"
|
||||
)
|
||||
|
||||
type storageRecorder struct {
|
||||
testutil.Recorder
|
||||
dbPath string // must have '/' suffix if set
|
||||
}
|
||||
|
||||
func NewStorageRecorder(db string) *storageRecorder {
|
||||
return &storageRecorder{&testutil.RecorderBuffered{}, db}
|
||||
}
|
||||
|
||||
func NewStorageRecorderStream(db string) *storageRecorder {
|
||||
return &storageRecorder{testutil.NewRecorderStream(), db}
|
||||
}
|
||||
|
||||
func (p *storageRecorder) Save(st raftpb.HardState, ents []raftpb.Entry) error {
|
||||
p.Record(testutil.Action{Name: "Save"})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *storageRecorder) SaveSnap(st raftpb.Snapshot) error {
|
||||
if !raft.IsEmptySnap(st) {
|
||||
p.Record(testutil.Action{Name: "SaveSnap"})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *storageRecorder) Release(st raftpb.Snapshot) error {
|
||||
if !raft.IsEmptySnap(st) {
|
||||
p.Record(testutil.Action{Name: "Release"})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *storageRecorder) Sync() error {
|
||||
p.Record(testutil.Action{Name: "Sync"})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *storageRecorder) Close() error { return nil }
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package mockstore provides mock structures for the etcd store package.
|
||||
package mockstore
|
||||
@@ -1,157 +0,0 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package mockstore
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/v3/etcdserver/api/v2store"
|
||||
"go.etcd.io/etcd/v3/pkg/testutil"
|
||||
)
|
||||
|
||||
// StoreRecorder provides a Store interface with a testutil.Recorder
|
||||
type StoreRecorder struct {
|
||||
v2store.Store
|
||||
testutil.Recorder
|
||||
}
|
||||
|
||||
// storeRecorder records all the methods it receives.
|
||||
// storeRecorder DOES NOT work as a actual v2store.
|
||||
// It always returns invalid empty response and no error.
|
||||
type storeRecorder struct {
|
||||
v2store.Store
|
||||
testutil.Recorder
|
||||
}
|
||||
|
||||
func NewNop() v2store.Store { return &storeRecorder{Recorder: &testutil.RecorderBuffered{}} }
|
||||
func NewRecorder() *StoreRecorder {
|
||||
sr := &storeRecorder{Recorder: &testutil.RecorderBuffered{}}
|
||||
return &StoreRecorder{Store: sr, Recorder: sr.Recorder}
|
||||
}
|
||||
func NewRecorderStream() *StoreRecorder {
|
||||
sr := &storeRecorder{Recorder: testutil.NewRecorderStream()}
|
||||
return &StoreRecorder{Store: sr, Recorder: sr.Recorder}
|
||||
}
|
||||
|
||||
func (s *storeRecorder) Version() int { return 0 }
|
||||
func (s *storeRecorder) Index() uint64 { return 0 }
|
||||
func (s *storeRecorder) Get(path string, recursive, sorted bool) (*v2store.Event, error) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "Get",
|
||||
Params: []interface{}{path, recursive, sorted},
|
||||
})
|
||||
return &v2store.Event{}, nil
|
||||
}
|
||||
func (s *storeRecorder) Set(path string, dir bool, val string, expireOpts v2store.TTLOptionSet) (*v2store.Event, error) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "Set",
|
||||
Params: []interface{}{path, dir, val, expireOpts},
|
||||
})
|
||||
return &v2store.Event{}, nil
|
||||
}
|
||||
func (s *storeRecorder) Update(path, val string, expireOpts v2store.TTLOptionSet) (*v2store.Event, error) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "Update",
|
||||
Params: []interface{}{path, val, expireOpts},
|
||||
})
|
||||
return &v2store.Event{}, nil
|
||||
}
|
||||
func (s *storeRecorder) Create(path string, dir bool, val string, uniq bool, expireOpts v2store.TTLOptionSet) (*v2store.Event, error) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "Create",
|
||||
Params: []interface{}{path, dir, val, uniq, expireOpts},
|
||||
})
|
||||
return &v2store.Event{}, nil
|
||||
}
|
||||
func (s *storeRecorder) CompareAndSwap(path, prevVal string, prevIdx uint64, val string, expireOpts v2store.TTLOptionSet) (*v2store.Event, error) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "CompareAndSwap",
|
||||
Params: []interface{}{path, prevVal, prevIdx, val, expireOpts},
|
||||
})
|
||||
return &v2store.Event{}, nil
|
||||
}
|
||||
func (s *storeRecorder) Delete(path string, dir, recursive bool) (*v2store.Event, error) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "Delete",
|
||||
Params: []interface{}{path, dir, recursive},
|
||||
})
|
||||
return &v2store.Event{}, nil
|
||||
}
|
||||
func (s *storeRecorder) CompareAndDelete(path, prevVal string, prevIdx uint64) (*v2store.Event, error) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "CompareAndDelete",
|
||||
Params: []interface{}{path, prevVal, prevIdx},
|
||||
})
|
||||
return &v2store.Event{}, nil
|
||||
}
|
||||
func (s *storeRecorder) Watch(_ string, _, _ bool, _ uint64) (v2store.Watcher, error) {
|
||||
s.Record(testutil.Action{Name: "Watch"})
|
||||
return v2store.NewNopWatcher(), nil
|
||||
}
|
||||
func (s *storeRecorder) Save() ([]byte, error) {
|
||||
s.Record(testutil.Action{Name: "Save"})
|
||||
return nil, nil
|
||||
}
|
||||
func (s *storeRecorder) Recovery(b []byte) error {
|
||||
s.Record(testutil.Action{Name: "Recovery"})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *storeRecorder) SaveNoCopy() ([]byte, error) {
|
||||
s.Record(testutil.Action{Name: "SaveNoCopy"})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *storeRecorder) Clone() v2store.Store {
|
||||
s.Record(testutil.Action{Name: "Clone"})
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *storeRecorder) JsonStats() []byte { return nil }
|
||||
func (s *storeRecorder) DeleteExpiredKeys(cutoff time.Time) {
|
||||
s.Record(testutil.Action{
|
||||
Name: "DeleteExpiredKeys",
|
||||
Params: []interface{}{cutoff},
|
||||
})
|
||||
}
|
||||
|
||||
func (s *storeRecorder) HasTTLKeys() bool {
|
||||
s.Record(testutil.Action{
|
||||
Name: "HasTTLKeys",
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// errStoreRecorder is a storeRecorder, but returns the given error on
|
||||
// Get, Watch methods.
|
||||
type errStoreRecorder struct {
|
||||
storeRecorder
|
||||
err error
|
||||
}
|
||||
|
||||
func NewErrRecorder(err error) *StoreRecorder {
|
||||
sr := &errStoreRecorder{err: err}
|
||||
sr.Recorder = &testutil.RecorderBuffered{}
|
||||
return &StoreRecorder{Store: sr, Recorder: sr.Recorder}
|
||||
}
|
||||
|
||||
func (s *errStoreRecorder) Get(path string, recursive, sorted bool) (*v2store.Event, error) {
|
||||
s.storeRecorder.Get(path, recursive, sorted)
|
||||
return nil, s.err
|
||||
}
|
||||
func (s *errStoreRecorder) Watch(path string, recursive, sorted bool, index uint64) (v2store.Watcher, error) {
|
||||
s.storeRecorder.Watch(path, recursive, sorted, index)
|
||||
return nil, s.err
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package mockwait provides mock implementations for pkg/wait.
|
||||
package mockwait
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright 2015 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package mockwait
|
||||
|
||||
import (
|
||||
"go.etcd.io/etcd/v3/pkg/testutil"
|
||||
"go.etcd.io/etcd/v3/pkg/wait"
|
||||
)
|
||||
|
||||
type WaitRecorder struct {
|
||||
wait.Wait
|
||||
testutil.Recorder
|
||||
}
|
||||
|
||||
type waitRecorder struct {
|
||||
testutil.RecorderBuffered
|
||||
}
|
||||
|
||||
func NewRecorder() *WaitRecorder {
|
||||
wr := &waitRecorder{}
|
||||
return &WaitRecorder{Wait: wr, Recorder: wr}
|
||||
}
|
||||
func NewNop() wait.Wait { return NewRecorder() }
|
||||
|
||||
func (w *waitRecorder) Register(id uint64) <-chan interface{} {
|
||||
w.Record(testutil.Action{Name: "Register"})
|
||||
return nil
|
||||
}
|
||||
func (w *waitRecorder) Trigger(id uint64, x interface{}) {
|
||||
w.Record(testutil.Action{Name: "Trigger"})
|
||||
}
|
||||
|
||||
func (w *waitRecorder) IsRegistered(id uint64) bool {
|
||||
panic("waitRecorder.IsRegistered() shouldn't be called")
|
||||
}
|
||||
Reference in New Issue
Block a user