tests/integration: Simplify the testMain for examples.

We introduce a LazyCluster abstraction (instead of copy-pasted logic)
that makes clusters to be created only if there are runnable tests
in need for the infrastructure.
This commit is contained in:
Piotr Tabor 2020-10-06 13:40:32 +02:00
parent 73b92fe688
commit c5ccebf792
5 changed files with 95 additions and 26 deletions

View File

@ -21,8 +21,8 @@ import (
"go.etcd.io/etcd/v3/pkg/testutil"
)
var exampleEndpoints []string
var exampleTransport *http.Transport
func exampleEndpoints() []string { return nil }
func exampleTransport() *http.Transport { return nil }
func forUnitTestsRunInMockedContext(mocking func(), example func()) {
mocking()

View File

@ -133,6 +133,8 @@ func interestingGoroutines() (gs []string) {
func MustCheckLeakedGoroutine() {
http.DefaultTransport.(*http.Transport).CloseIdleConnections()
CheckAfterTest(5 * time.Second)
// Let the other goroutines finalize.
runtime.Gosched()

View File

@ -34,8 +34,8 @@ func ExampleKeysAPI_directory() {
mockKeysAPI_directory,
func() {
c, err := client.New(client.Config{
Endpoints: exampleEndpoints,
Transport: exampleTransport,
Endpoints: exampleEndpoints(),
Transport: exampleTransport(),
})
if err != nil {
log.Fatal(err)
@ -85,8 +85,8 @@ func ExampleKeysAPI_setget() {
mockKeysAPI_setget,
func() {
c, err := client.New(client.Config{
Endpoints: exampleEndpoints,
Transport: exampleTransport,
Endpoints: exampleEndpoints(),
Transport: exampleTransport(),
})
if err != nil {
log.Fatal(err)

View File

@ -15,19 +15,18 @@
package client_test
import (
"fmt"
"net/http"
"os"
"testing"
"time"
"go.etcd.io/etcd/tests/v3/integration"
"go.etcd.io/etcd/v3/pkg/testutil"
"go.etcd.io/etcd/v3/pkg/transport"
)
var exampleEndpoints []string
var exampleTransport *http.Transport
var lazyCluster = integration.NewLazyCluster()
func exampleEndpoints() []string { return lazyCluster.EndpointsV2() }
func exampleTransport() *http.Transport { return lazyCluster.Transport() }
func forUnitTestsRunInMockedContext(mocking func(), example func()) {
// For integration tests runs in the provided environment
@ -36,22 +35,8 @@ func forUnitTestsRunInMockedContext(mocking func(), example func()) {
// TestMain sets up an etcd cluster if running the examples.
func TestMain(m *testing.M) {
tr, trerr := transport.NewTransport(transport.TLSInfo{}, time.Second)
if trerr != nil {
fmt.Fprintf(os.Stderr, "%v", trerr)
os.Exit(1)
}
cfg := integration.ClusterConfig{Size: 1}
clus := integration.NewClusterV3(nil, &cfg)
exampleEndpoints = []string{clus.Members[0].URL()}
exampleTransport = tr
v := m.Run()
clus.Terminate(nil)
if err := testutil.CheckAfterTest(time.Second); err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
os.Exit(1)
}
lazyCluster.Terminate()
if v == 0 {
testutil.MustCheckLeakedGoroutine()
}

View File

@ -0,0 +1,82 @@
// Copyright 2020 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 integration
import (
"log"
"net/http"
"sync"
"time"
"go.etcd.io/etcd/v3/pkg/transport"
)
type LazyCluster interface {
// EndpointsV2 - call to this method might initialize the cluster.
EndpointsV2() []string
// EndpointsV2 - call to this method might initialize the cluster.
EndpointsV3() []string
// Transport - call to this method might initialize the cluster.
Transport() *http.Transport
Terminate()
}
type lazyCluster struct {
cfg ClusterConfig
cluster *ClusterV3
transport *http.Transport
once sync.Once
}
// NewLazyCluster returns a new test cluster handler that gets created on the
// first call to GetEndpoints() or GetTransport()
func NewLazyCluster() LazyCluster {
return &lazyCluster{cfg: ClusterConfig{Size: 1}}
}
func (lc *lazyCluster) mustLazyInit() {
lc.once.Do(func() {
var err error
lc.transport, err = transport.NewTransport(transport.TLSInfo{}, time.Second)
if err != nil {
log.Fatal(err)
}
lc.cluster = NewClusterV3(nil, &lc.cfg)
})
}
func (lc *lazyCluster) Terminate() {
if lc != nil {
lc.cluster.Terminate(nil)
}
}
func (lc *lazyCluster) EndpointsV2() []string {
lc.mustLazyInit()
return []string{lc.cluster.Members[0].URL()}
}
func (lc *lazyCluster) EndpointsV3() []string {
lc.mustLazyInit()
return []string{lc.cluster.Client(0).Endpoints()[0]}
}
func (lc *lazyCluster) Transport() *http.Transport {
lc.mustLazyInit()
return lc.transport
}