github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/framework/integration/testing.go (about) 1 // Copyright 2021 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package integration 16 17 import ( 18 "os" 19 "path/filepath" 20 "testing" 21 22 grpc_logsettable "github.com/grpc-ecosystem/go-grpc-middleware/logging/settable" 23 "github.com/lfch/etcd-io/client/pkg/v3/testutil" 24 "github.com/lfch/etcd-io/client/pkg/v3/verify" 25 clientv3 "github.com/lfch/etcd-io/client/v3" 26 "github.com/lfch/etcd-io/server/v3/embed" 27 "go.uber.org/zap/zapcore" 28 "go.uber.org/zap/zapgrpc" 29 "go.uber.org/zap/zaptest" 30 ) 31 32 var grpc_logger grpc_logsettable.SettableLoggerV2 33 var insideTestContext bool 34 35 func init() { 36 grpc_logger = grpc_logsettable.ReplaceGrpcLoggerV2() 37 } 38 39 type testOptions struct { 40 goLeakDetection bool 41 skipInShort bool 42 } 43 44 func newTestOptions(opts ...TestOption) *testOptions { 45 o := &testOptions{goLeakDetection: true, skipInShort: true} 46 for _, opt := range opts { 47 opt(o) 48 } 49 return o 50 } 51 52 type TestOption func(opt *testOptions) 53 54 // WithoutGoLeakDetection disables checking whether a testcase leaked a goroutine. 55 func WithoutGoLeakDetection() TestOption { 56 return func(opt *testOptions) { opt.goLeakDetection = false } 57 } 58 59 func WithoutSkipInShort() TestOption { 60 return func(opt *testOptions) { opt.skipInShort = false } 61 } 62 63 // BeforeTestExternal initializes test context and is targeted for external APIs. 64 // In general the `integration` package is not targeted to be used outside of 65 // etcd project, but till the dedicated package is developed, this is 66 // the best entry point so far (without backward compatibility promise). 67 func BeforeTestExternal(t testutil.TB) { 68 BeforeTest(t, WithoutSkipInShort(), WithoutGoLeakDetection()) 69 } 70 71 func BeforeTest(t testutil.TB, opts ...TestOption) { 72 t.Helper() 73 options := newTestOptions(opts...) 74 75 if insideTestContext { 76 t.Fatal("already in test context. BeforeTest was likely already called") 77 } 78 79 if options.skipInShort { 80 testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests") 81 } 82 83 if options.goLeakDetection { 84 testutil.RegisterLeakDetection(t) 85 } 86 87 previousWD, err := os.Getwd() 88 if err != nil { 89 t.Fatal(err) 90 } 91 previousInsideTestContext := insideTestContext 92 93 // Integration tests should verify written state as much as possible. 94 revertFunc := verify.EnableAllVerifications() 95 96 // Registering cleanup early, such it will get executed even if the helper fails. 97 t.Cleanup(func() { 98 grpc_logger.Reset() 99 insideTestContext = previousInsideTestContext 100 os.Chdir(previousWD) 101 revertFunc() 102 }) 103 104 grpc_logger.Set(zapgrpc.NewLogger(zaptest.NewLogger(t).Named("grpc"))) 105 insideTestContext = true 106 107 os.Chdir(t.TempDir()) 108 } 109 110 func assertInTestContext(t testutil.TB) { 111 if !insideTestContext { 112 t.Errorf("the function can be called only in the test context. Was integration.BeforeTest() called ?") 113 } 114 } 115 116 func MustAbsPath(path string) string { 117 abs, err := filepath.Abs(path) 118 if err != nil { 119 panic(err) 120 } 121 return abs 122 } 123 124 func NewEmbedConfig(t testing.TB, name string) *embed.Config { 125 cfg := embed.NewConfig() 126 cfg.Name = name 127 lg := zaptest.NewLogger(t, zaptest.Level(zapcore.InfoLevel)).Named(cfg.Name) 128 cfg.ZapLoggerBuilder = embed.NewZapLoggerBuilder(lg) 129 cfg.Dir = t.TempDir() 130 return cfg 131 } 132 133 func NewClient(t testing.TB, cfg clientv3.Config) (*clientv3.Client, error) { 134 if cfg.Logger == nil { 135 cfg.Logger = zaptest.NewLogger(t).Named("client") 136 } 137 return clientv3.New(cfg) 138 }