go.etcd.io/etcd@v3.3.27+incompatible/tests/e2e/util.go (about)

     1  // Copyright 2017 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 e2e
    16  
    17  import (
    18  	"encoding/json"
    19  	"fmt"
    20  	"math/rand"
    21  	"strings"
    22  	"time"
    23  
    24  	"github.com/coreos/etcd/pkg/expect"
    25  )
    26  
    27  func waitReadyExpectProc(exproc *expect.ExpectProcess, readyStrs []string) error {
    28  	c := 0
    29  	matchSet := func(l string) bool {
    30  		for _, s := range readyStrs {
    31  			if strings.Contains(l, s) {
    32  				c++
    33  				break
    34  			}
    35  		}
    36  		return c == len(readyStrs)
    37  	}
    38  	_, err := exproc.ExpectFunc(matchSet)
    39  	return err
    40  }
    41  
    42  func spawnWithExpect(args []string, expected string) error {
    43  	return spawnWithExpects(args, []string{expected}...)
    44  }
    45  
    46  func spawnWithExpects(args []string, xs ...string) error {
    47  	_, err := spawnWithExpectLines(args, xs...)
    48  	return err
    49  }
    50  
    51  func spawnWithExpectLines(args []string, xs ...string) ([]string, error) {
    52  	proc, err := spawnCmd(args)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	// process until either stdout or stderr contains
    57  	// the expected string
    58  	var (
    59  		lines    []string
    60  		lineFunc = func(txt string) bool { return true }
    61  	)
    62  	for _, txt := range xs {
    63  		for {
    64  			l, lerr := proc.ExpectFunc(lineFunc)
    65  			if lerr != nil {
    66  				proc.Close()
    67  				return nil, fmt.Errorf("%v (expected %q, got %q)", lerr, txt, lines)
    68  			}
    69  			lines = append(lines, l)
    70  			if strings.Contains(l, txt) {
    71  				break
    72  			}
    73  		}
    74  	}
    75  	perr := proc.Close()
    76  	if len(xs) == 0 && proc.LineCount() != noOutputLineCount { // expect no output
    77  		return nil, fmt.Errorf("unexpected output (got lines %q, line count %d)", lines, proc.LineCount())
    78  	}
    79  	return lines, perr
    80  }
    81  
    82  func randomLeaseID() int64 {
    83  	return rand.New(rand.NewSource(time.Now().UnixNano())).Int63()
    84  }
    85  
    86  func dataMarshal(data interface{}) (d string, e error) {
    87  	m, err := json.Marshal(data)
    88  	if err != nil {
    89  		return "", err
    90  	}
    91  	return string(m), nil
    92  }
    93  
    94  func closeWithTimeout(p *expect.ExpectProcess, d time.Duration) error {
    95  	errc := make(chan error, 1)
    96  	go func() { errc <- p.Close() }()
    97  	select {
    98  	case err := <-errc:
    99  		return err
   100  	case <-time.After(d):
   101  		p.Stop()
   102  		// retry close after stopping to collect SIGQUIT data, if any
   103  		closeWithTimeout(p, time.Second)
   104  	}
   105  	return fmt.Errorf("took longer than %v to Close process %+v", d, p)
   106  }
   107  
   108  func toTLS(s string) string {
   109  	return strings.Replace(s, "http://", "https://", 1)
   110  }