get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/test/test_test.go (about)

     1  // Copyright 2016-2020 The NATS Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package test
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"net"
    20  	"strconv"
    21  	"strings"
    22  	"sync"
    23  	"testing"
    24  	"time"
    25  
    26  	"get.pme.sh/pnats/server"
    27  	"golang.org/x/time/rate"
    28  )
    29  
    30  func checkFor(t testing.TB, totalWait, sleepDur time.Duration, f func() error) {
    31  	t.Helper()
    32  	timeout := time.Now().Add(totalWait)
    33  	var err error
    34  	for time.Now().Before(timeout) {
    35  		err = f()
    36  		if err == nil {
    37  			return
    38  		}
    39  		time.Sleep(sleepDur)
    40  	}
    41  	if err != nil {
    42  		t.Fatal(err.Error())
    43  	}
    44  }
    45  
    46  // Slow Proxy - For introducing RTT and BW constraints.
    47  type slowProxy struct {
    48  	listener net.Listener
    49  	conns    []net.Conn
    50  	o        *server.Options
    51  	u        string
    52  }
    53  
    54  func newSlowProxy(rtt time.Duration, up, down int, opts *server.Options) *slowProxy {
    55  	saddr := net.JoinHostPort(opts.Host, strconv.Itoa(opts.Port))
    56  	hp := net.JoinHostPort("127.0.0.1", "0")
    57  	l, e := net.Listen("tcp", hp)
    58  	if e != nil {
    59  		panic(fmt.Sprintf("Error listening on port: %s, %q", hp, e))
    60  	}
    61  	port := l.Addr().(*net.TCPAddr).Port
    62  	sp := &slowProxy{listener: l}
    63  	go func() {
    64  		client, err := l.Accept()
    65  		if err != nil {
    66  			return
    67  		}
    68  		server, err := net.DialTimeout("tcp", saddr, time.Second)
    69  		if err != nil {
    70  			panic("Can't connect to server")
    71  		}
    72  		sp.conns = append(sp.conns, client, server)
    73  		go sp.loop(rtt, up, client, server)
    74  		go sp.loop(rtt, down, server, client)
    75  	}()
    76  	sp.o = &server.Options{Host: "127.0.0.1", Port: port}
    77  	sp.u = fmt.Sprintf("nats://%s:%d", sp.o.Host, sp.o.Port)
    78  	return sp
    79  }
    80  
    81  func (sp *slowProxy) opts() *server.Options {
    82  	return sp.o
    83  }
    84  
    85  //lint:ignore U1000 Referenced in norace_test.go
    86  func (sp *slowProxy) clientURL() string {
    87  	return sp.u
    88  }
    89  
    90  func (sp *slowProxy) loop(rtt time.Duration, tbw int, r, w net.Conn) {
    91  	delay := rtt / 2
    92  	const rbl = 1024
    93  	var buf [rbl]byte
    94  	ctx := context.Background()
    95  
    96  	rl := rate.NewLimiter(rate.Limit(tbw), rbl)
    97  
    98  	for fr := true; ; {
    99  		sr := time.Now()
   100  		n, err := r.Read(buf[:])
   101  		if err != nil {
   102  			return
   103  		}
   104  		// RTT delays
   105  		if fr || time.Since(sr) > 2*time.Millisecond {
   106  			fr = false
   107  			time.Sleep(delay)
   108  		}
   109  		if err := rl.WaitN(ctx, n); err != nil {
   110  			return
   111  		}
   112  		if _, err = w.Write(buf[:n]); err != nil {
   113  			return
   114  		}
   115  	}
   116  }
   117  
   118  func (sp *slowProxy) stop() {
   119  	if sp.listener != nil {
   120  		sp.listener.Close()
   121  		sp.listener = nil
   122  		for _, c := range sp.conns {
   123  			c.Close()
   124  		}
   125  	}
   126  }
   127  
   128  // Dummy Logger
   129  type dummyLogger struct {
   130  	sync.Mutex
   131  	msg string
   132  }
   133  
   134  func (d *dummyLogger) Fatalf(format string, args ...interface{}) {
   135  	d.Lock()
   136  	d.msg = fmt.Sprintf(format, args...)
   137  	d.Unlock()
   138  }
   139  
   140  func (d *dummyLogger) Errorf(format string, args ...interface{}) {
   141  }
   142  
   143  func (d *dummyLogger) Debugf(format string, args ...interface{}) {
   144  }
   145  
   146  func (d *dummyLogger) Tracef(format string, args ...interface{}) {
   147  }
   148  
   149  func (d *dummyLogger) Noticef(format string, args ...interface{}) {
   150  }
   151  
   152  func (d *dummyLogger) Warnf(format string, args ...interface{}) {
   153  }
   154  
   155  func TestStackFatal(t *testing.T) {
   156  	d := &dummyLogger{}
   157  	stackFatalf(d, "test stack %d", 1)
   158  	if !strings.HasPrefix(d.msg, "test stack 1") {
   159  		t.Fatalf("Unexpected start of stack: %v", d.msg)
   160  	}
   161  	if !strings.Contains(d.msg, "test_test.go") {
   162  		t.Fatalf("Unexpected stack: %v", d.msg)
   163  	}
   164  }