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  }