Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package fortio for openSUSE:Factory checked in at 2023-01-26 13:58:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fortio (Old) and /work/SRC/openSUSE:Factory/.fortio.new.32243 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fortio" Thu Jan 26 13:58:54 2023 rev:27 rq:1061117 version:1.40.0 Changes: -------- --- /work/SRC/openSUSE:Factory/fortio/fortio.changes 2023-01-20 17:39:30.448795768 +0100 +++ /work/SRC/openSUSE:Factory/.fortio.new.32243/fortio.changes 2023-01-26 13:59:37.988533234 +0100 @@ -1,0 +2,10 @@ +Thu Jan 26 06:37:36 UTC 2023 - ka...@b1-systems.de + +- Update to version 1.40.0: + * Add support for echo server https when cert/key are provided (like for grpc server) and h2 (http/2.0) option for client (#688) + * Bump google.golang.org/grpc from 1.52.0 to 1.52.1 (#691) + * log.FErrf like log.Fatalf but without the panic nor exit (#686) + * Bump github/codeql-action from 2.1.38 to 2.1.39 (#689) + * correct readme to match current 1.39.1 release. also fix #680 - pass the fortio useragent to grpc (#685) + +------------------------------------------------------------------- Old: ---- fortio-1.39.1.tar.gz New: ---- fortio-1.40.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fortio.spec ++++++ --- /var/tmp/diff_new_pack.5Y08p5/_old 2023-01-26 13:59:38.564536340 +0100 +++ /var/tmp/diff_new_pack.5Y08p5/_new 2023-01-26 13:59:38.568536362 +0100 @@ -19,7 +19,7 @@ %define __arch_install_post export NO_BRP_STRIP_DEBUG=true Name: fortio -Version: 1.39.1 +Version: 1.40.0 Release: 0 Summary: Load testing library, command line tool, advanced echo server and web UI License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.5Y08p5/_old 2023-01-26 13:59:38.608536578 +0100 +++ /var/tmp/diff_new_pack.5Y08p5/_new 2023-01-26 13:59:38.608536578 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/fortio/fortio</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v1.39.1</param> + <param name="revision">v1.40.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> <param name="versionrewrite-pattern">v(.*)</param> @@ -17,7 +17,7 @@ <param name="compression">gz</param> </service> <service name="go_modules" mode="disabled"> - <param name="archive">fortio-1.39.1.tar.gz</param> + <param name="archive">fortio-1.40.0.tar.gz</param> </service> </services> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.5Y08p5/_old 2023-01-26 13:59:38.628536686 +0100 +++ /var/tmp/diff_new_pack.5Y08p5/_new 2023-01-26 13:59:38.632536708 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/fortio/fortio</param> - <param name="changesrevision">d40d4b4a04025e12a96d9e75534a9e40c988c568</param></service></servicedata> + <param name="changesrevision">43a882efd38f26ec6d70685090c6fdc78b1821de</param></service></servicedata> (No newline at EOF) ++++++ fortio-1.39.1.tar.gz -> fortio-1.40.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/.github/workflows/codeql-analysis.yml new/fortio-1.40.0/.github/workflows/codeql-analysis.yml --- old/fortio-1.39.1/.github/workflows/codeql-analysis.yml 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/.github/workflows/codeql-analysis.yml 2023-01-25 17:39:53.000000000 +0100 @@ -44,7 +44,7 @@ # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@515828d97454b8354517688ddc5b48402b723750 # pin@v2 + uses: github/codeql-action/init@a34ca99b4610d924e04c68db79e503e1f79f9f02 # pin@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -55,7 +55,7 @@ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@515828d97454b8354517688ddc5b48402b723750 # pin@v2 + uses: github/codeql-action/autobuild@a34ca99b4610d924e04c68db79e503e1f79f9f02 # pin@v2 # â¹ï¸ Command-line programs to run using the OS shell. # ð https://git.io/JvXDl @@ -66,4 +66,4 @@ # make bootstrap # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@515828d97454b8354517688ddc5b48402b723750 # pin@v2 + uses: github/codeql-action/analyze@a34ca99b4610d924e04c68db79e503e1f79f9f02 # pin@v2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/.golangci.yml new/fortio-1.40.0/.golangci.yml --- old/fortio-1.39.1/.golangci.yml 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/.golangci.yml 2023-01-25 17:39:53.000000000 +0100 @@ -42,6 +42,7 @@ - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Printf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).FErrf enable-all: true disable-all: false depguard: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/README.md new/fortio-1.40.0/README.md --- old/fortio-1.39.1/README.md 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/README.md 2023-01-25 17:39:53.000000000 +0100 @@ -54,13 +54,13 @@ The [releases](https://github.com/fortio/fortio/releases) page has binaries for many OS/architecture combinations (see assets): ```shell -curl -L https://github.com/fortio/fortio/releases/download/v1.39.0/fortio-linux_amd64-1.39.0.tgz \ +curl -L https://github.com/fortio/fortio/releases/download/v1.40.0/fortio-linux_amd64-1.40.0.tgz \ | sudo tar -C / -xvzpf - # or the debian package -wget https://github.com/fortio/fortio/releases/download/v1.39.0/fortio_1.39.0_amd64.deb -dpkg -i fortio_1.39.0_amd64.deb +wget https://github.com/fortio/fortio/releases/download/v1.40.0/fortio_1.40.0_amd64.deb +dpkg -i fortio_1.40.0_amd64.deb # or the rpm -rpm -i https://github.com/fortio/fortio/releases/download/v1.39.0/fortio-1.39.0-1.x86_64.rpm +rpm -i https://github.com/fortio/fortio/releases/download/v1.40.0/fortio-1.40.0-1.x86_64.rpm # and more, see assets in release page ``` @@ -70,7 +70,7 @@ brew install fortio ``` -On Windows, download https://github.com/fortio/fortio/releases/download/v1.39.0/fortio_win_1.39.0.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt: +On Windows, download https://github.com/fortio/fortio/releases/download/v1.40.0/fortio_win_1.40.0.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt: ``` fortio.exe server ``` @@ -111,6 +111,7 @@ | `-a` | Automatically save JSON result with filename based on labels and timestamp | | `-json filename` | Filename or `-` for stdout to output json result (relative to `-data-dir` by default, should end with .json if you want `fortio report` to show them; using `-a` is typicallly a better option)| | `-labels "l1 l2 ..."` | Additional config data/labels to add to the resulting JSON, defaults to target URL and hostname| +| `-h2` | Client calls will attempt to negotiate http/2.0 instead of http1.1, implies `-stdclient`| You can switch from http GET queries to POST by setting `-content-type` or passing one of the `-payload-*` option. @@ -118,7 +119,7 @@ <details> <!-- use release/updateFlags.sh to update this section --> <pre> -ΦοÏÏίο 1.39.0 usage: +ΦοÏÏίο 1.40.0 usage: fortio command [flags] target where command is one of: load (load testing), server (starts ui, rest api, http-echo, redirect, proxies, tcp-echo, udp-echo and grpc ping servers), @@ -204,6 +205,8 @@ grpc server port. Can be in the form of host:port, ip:port or port or /unix/domain/path or "disabled" to not start the grpc server. (default "8079") -h Print usage/help on stdout + -h2 + Attempt to use http2.0 / h2 (instead of http 1.1) with stdclient and TLS -halfclose When not keepalive, whether to half close the connection (only for fast http) @@ -240,6 +243,9 @@ Log http non 2xx/418 error codes as they occur (default true) -logcaller Logs filename and line number of callers to log (default true) + -logfatalpanics + If true, log.Fatal will panic (stack trace) instead of just exit 1 +(default true) -loglevel value loglevel, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info) @@ -570,6 +576,10 @@ #### `grpcping` using TLS +Note that since 1.40 the same applies to the main http server port, it will listen on TLS if `-cert` and `-key` flags are provided. + +For testing use `make certs` to generate self signed test certificates. + * First, start Fortio server with the `-cert` and `-key` flags: `/path/to/fortio/server.crt` and `/path/to/fortio/server.key` are paths to the TLS certificate and key that diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/bincommon/commonflags.go new/fortio-1.40.0/bincommon/commonflags.go --- old/fortio-1.39.1/bincommon/commonflags.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/bincommon/commonflags.go 2023-01-25 17:39:53.000000000 +0100 @@ -71,6 +71,7 @@ httpReqTimeoutFlag = flag.Duration("timeout", fhttp.HTTPReqTimeOutDefaultValue, "Connection and read timeout value (for http)") stdClientFlag = flag.Bool("stdclient", false, "Use the slower net/http standard client (slower but supports h2)") http10Flag = flag.Bool("http1.0", false, "Use http1.0 (instead of http 1.1)") + h2Flag = flag.Bool("h2", false, "Attempt to use http2.0 / h2 (instead of http 1.1) with stdclient and TLS") httpsInsecureFlag = flag.Bool("k", false, "Do not verify certs in https/tls/grpc connections") httpsInsecureFlagL = flag.Bool("https-insecure", false, "Long form of the -k flag") resolve = flag.String("resolve", "", "Resolve host name to this `IP`") @@ -204,6 +205,7 @@ url := strings.TrimLeft(flag.Arg(0), " \t\r\n") httpOpts.URL = url httpOpts.HTTP10 = *http10Flag + httpOpts.H2 = *h2Flag httpOpts.DisableFastClient = *stdClientFlag httpOpts.DisableKeepAlive = !*keepAliveFlag httpOpts.AllowHalfClose = *halfCloseFlag diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/echosrv/echo.go new/fortio-1.40.0/echosrv/echo.go --- old/fortio-1.39.1/echosrv/echo.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/echosrv/echo.go 2023-01-25 17:39:53.000000000 +0100 @@ -32,6 +32,8 @@ var ( port = flag.String("port", "8080", "default http port, either port or address:port can be specified") debugPath = flag.String("debug-path", "/debug", "path for debug url, set to empty for no debug") + certFlag = flag.String("cert", "", "`Path` to the certificate file to be used for client or server TLS") + keyFlag = flag.String("key", "", "`Path` to the key file matching the -cert") ) func main() { @@ -40,7 +42,7 @@ fmt.Println(version.Full()) os.Exit(0) } - if _, addr := fhttp.Serve(*port, *debugPath); addr == nil { + if _, addr := fhttp.ServeTLS(*port, *debugPath, *certFlag, *keyFlag); addr == nil { os.Exit(1) // error already logged } select {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/fgrpc/grpcrunner.go new/fortio-1.40.0/fgrpc/grpcrunner.go --- old/fortio-1.39.1/fgrpc/grpcrunner.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/fgrpc/grpcrunner.go 2023-01-25 17:39:53.000000000 +0100 @@ -26,7 +26,6 @@ "fortio.org/fortio/fhttp" "fortio.org/fortio/fnet" - "fortio.org/fortio/jrpc" "fortio.org/fortio/log" "fortio.org/fortio/periodic" "google.golang.org/grpc" @@ -320,11 +319,6 @@ // Transfer these 2 and avoid having them duplicated in original MD case "user-agent": delete(in, k) - // TODO: remove when #680 is figured out. - if v[0] == jrpc.UserAgent { - // for keeping the same behavior as before, unless this is set by the user - continue - } out = append(out, grpc.WithUserAgent(v[0])) case "host": delete(in, k) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/fgrpc/grpcrunner_test.go new/fortio-1.40.0/fgrpc/grpcrunner_test.go --- old/fortio-1.39.1/fgrpc/grpcrunner_test.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/fgrpc/grpcrunner_test.go 2023-01-25 17:39:53.000000000 +0100 @@ -524,7 +524,7 @@ "host": {"a.b"}, }, }, - wantOutLen: 1, + wantOutLen: 2, wantMD: map[string][]string{}, }, { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/fgrpc/pingsrv.go new/fortio-1.40.0/fgrpc/pingsrv.go --- old/fortio-1.39.1/fgrpc/pingsrv.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/fgrpc/pingsrv.go 2023-01-25 17:39:53.000000000 +0100 @@ -77,10 +77,9 @@ if cert != "" && key != "" { creds, err := credentials.NewServerTLSFromFile(cert, key) if err != nil { - log.Fatalf("Invalid TLS credentials: %v\n", err) + log.Fatalf("Invalid TLS credentials: %v", err) } - log.Infof("Using server certificate %v to construct TLS credentials", cert) - log.Infof("Using server key %v to construct TLS credentials", key) + log.Infof("Using server certificate %v and key %v to construct TLS credentials", cert, key) grpcOptions = append(grpcOptions, grpc.Creds(creds)) } grpcServer := grpc.NewServer(grpcOptions...) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/fhttp/http_client.go new/fortio-1.40.0/fhttp/http_client.go --- old/fortio-1.39.1/fhttp/http_client.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/fhttp/http_client.go 2023-01-25 17:39:53.000000000 +0100 @@ -140,6 +140,10 @@ log.Errf("Unexpected init with empty url") return } + if h.H2 && !h.DisableFastClient { + log.Infof("H2 requested, switching to std client") + h.DisableFastClient = true + } hs := "https://" // longer of the 2 prefixes lcURL := h.URL if len(lcURL) > len(hs) { @@ -169,6 +173,7 @@ Compression bool // defaults to no compression, only used by std client DisableFastClient bool // defaults to fast client HTTP10 bool // defaults to http1.1 + H2 bool // defaults to http1.1 (h2 only for stdclient) DisableKeepAlive bool // so default is keep alive AllowHalfClose bool // if not keepalive, whether to half close after request FollowRedirects bool // For the Std Client only: follow redirects. @@ -554,6 +559,7 @@ return conn, err }, TLSHandshakeTimeout: o.HTTPReqTimeOut, + ForceAttemptHTTP2: o.H2, } var rt http.RoundTripper = &tr if o.Transport != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/fhttp/http_server.go new/fortio-1.40.0/fhttp/http_server.go --- old/fortio-1.39.1/fhttp/http_server.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/fhttp/http_server.go 2023-01-25 17:39:53.000000000 +0100 @@ -17,6 +17,7 @@ // pprof import to get /debug/pprof endpoints on a mux through SetupPPROF. import ( "bytes" + "crypto/tls" "flag" "fmt" "io" @@ -205,6 +206,26 @@ return addr } +func HTTPSServer(name string, port string, certFile string, keyFile string) (*http.ServeMux, net.Addr) { + listener, addr := fnet.Listen(name, port) + if listener == nil { + return nil, nil // error already logged + } + m := http.NewServeMux() + s := &http.Server{ + ReadHeaderTimeout: serverIdleTimeout.Get(), + IdleTimeout: serverIdleTimeout.Get(), + Handler: m, + } + go func() { + err := s.ServeTLS(listener, certFile, keyFile) + if err != nil { + log.Fatalf("Unable to TLS serve %s on %s: %v", name, addr.String(), err) + } + }() + return m, addr +} + // DynamicHTTPServer listens on an available port, sets up an http or a closing // server simulating an https server (when closing is true) server on it and // returns the listening port and mux to which one can attach handlers to. @@ -287,6 +308,7 @@ buf.WriteString(hostname) buf.WriteString(" - request from ") buf.WriteString(r.RemoteAddr) + buf.WriteString(TLSInfo(r)) buf.WriteString("\n\n") buf.WriteString(r.Method) buf.WriteByte(' ') @@ -371,8 +393,20 @@ // The .Port can be retrieved from it when requesting the 0 port as // input for dynamic http server. func Serve(port, debugPath string) (*http.ServeMux, net.Addr) { + return ServeTLS(port, debugPath, "", "") +} + +// ServeTLS starts a debug / echo server on the given port, +// using TLS if certPath and keyPath aren't not empty. +func ServeTLS(port, debugPath, certPath, keyPath string) (*http.ServeMux, net.Addr) { startTime = time.Now() - mux, addr := HTTPServer("http-echo", port) + var mux *http.ServeMux + var addr net.Addr + if certPath != "" && keyPath != "" { + mux, addr = HTTPSServer("https-echo", port, certPath, keyPath) + } else { + mux, addr = HTTPServer("http-echo", port) + } if addr == nil { return nil, nil // error already logged } @@ -510,11 +544,20 @@ return a } +// TLSInfo returns " https <cipher suite>" if the request is using TLS, or "" otherwise. +func TLSInfo(r *http.Request) string { + if r.TLS == nil { + return "" + } + return fmt.Sprintf(" https %s", tls.CipherSuiteName(r.TLS.CipherSuite)) +} + // LogRequest logs the incoming request, including headers when loglevel is verbose. func LogRequest(r *http.Request, msg string) { if log.Log(log.Info) { - log.Printf("%s: %v %v %v %v (%s) %s %q", msg, r.Method, r.URL, r.Proto, r.RemoteAddr, - r.Header.Get("X-Forwarded-Proto"), r.Header.Get("X-Forwarded-For"), r.Header.Get("User-Agent")) + tlsInfo := TLSInfo(r) + log.Printf("%s: %v %v %v %v (%v) %s %q%s", msg, r.Method, r.URL, r.Proto, r.RemoteAddr, + r.Header.Get("X-Forwarded-Proto"), r.Header.Get("X-Forwarded-For"), r.Header.Get("User-Agent"), tlsInfo) } if log.LogVerbose() { // Host is removed from headers map and put separately diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/fhttp/https_server_test.go new/fortio-1.40.0/fhttp/https_server_test.go --- old/fortio-1.39.1/fhttp/https_server_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/fortio-1.40.0/fhttp/https_server_test.go 2023-01-25 17:39:53.000000000 +0100 @@ -0,0 +1,92 @@ +// Copyright 2023 Fortio 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 fhttp + +import ( + "context" + "fmt" + "net" + "net/http" + "strings" + "sync/atomic" + "testing" + "time" + + "fortio.org/fortio/fnet" + "fortio.org/fortio/log" +) + +var ( + // Generated from "make cert". + caCrt = "../cert-tmp/ca.crt" + svrCrt = "../cert-tmp/server.crt" + svrKey = "../cert-tmp/server.key" +) + +func TestHTTPSServer(t *testing.T) { + // log.SetLogLevel(log.Debug) + m, a := ServeTLS("0", "/debug", svrCrt, svrKey) + if m == nil || a == nil { + t.Errorf("Failed to create server %v %v", m, a) + } + url := fmt.Sprintf("https://localhost:%d/debug", a.(*net.TCPAddr).Port) + // Triggers the h2->DisableFastClient normalization code too. + o := HTTPOptions{URL: url, TLSOptions: TLSOptions{CACert: caCrt}, H2: true} + client, _ := NewClient(&o) + code, data, header := client.Fetch(context.Background()) + t.Logf("TestDebugHandlerSortedHeaders result code %d, data len %d, headerlen %d", code, len(data), header) + if code != http.StatusOK { + t.Errorf("Got %d instead of 200", code) + } + body := string(data) + if !strings.Contains(body, "https TLS_") { + t.Errorf("Missing https TLS_ in body: %s", body) + } + if !strings.Contains(body, "HTTP/2.0") { + t.Errorf("Missing HTTP/2.0 in body: %s", body) + } +} + +func TestHTTPSServerError(t *testing.T) { + _, addr := ServeTLS("0", "", svrCrt, svrKey) + port := fnet.GetPort(addr) + mux2, addr2 := ServeTLS(port, "", svrCrt, svrKey) + if mux2 != nil || addr2 != nil { + t.Errorf("2nd Serve() on same port %v should have failed: %v %v", port, mux2, addr2) + } +} + +func TestHTTPSServerMissingCert(t *testing.T) { + fatalCalled := atomic.Bool{} + fatalCalled.Store(false) + log.FatalExit = func(int) { + t.Logf("FatalExit called") + fatalCalled.Store(true) + } + log.SetFlagDefaultsForClientTools() + _, addr := ServeTLS("0", "", "/foo/bar.crt", "/foo/bar.key") + url := fmt.Sprintf("https://localhost:%d/debug", addr.(*net.TCPAddr).Port) + o := HTTPOptions{URL: url, TLSOptions: TLSOptions{CACert: caCrt}, H2: true, HTTPReqTimeOut: 100 * time.Millisecond} + client, _ := NewClient(&o) + code, data, header := client.Fetch(context.Background()) + t.Logf("TestDebugHandlerSortedHeaders result code %d, data len %d, headerlen %d", code, len(data), header) + if code != -1 { + t.Errorf("Got %d instead of expected error", code) + } + if !fatalCalled.Load() { + t.Errorf("FatalExit not called") + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/go.mod new/fortio-1.40.0/go.mod --- old/fortio-1.39.1/go.mod 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/go.mod 2023-01-25 17:39:53.000000000 +0100 @@ -9,7 +9,7 @@ github.com/google/uuid v1.3.0 golang.org/x/exp v0.0.0-20221111204811-129d8d6c17ab golang.org/x/net v0.5.0 - google.golang.org/grpc v1.52.0 + google.golang.org/grpc v1.52.1 ) require ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/go.sum new/fortio-1.40.0/go.sum --- old/fortio-1.39.1/go.sum 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/go.sum 2023-01-25 17:39:53.000000000 +0100 @@ -21,8 +21,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.52.1 h1:2NpOPk5g5Xtb0qebIEs7hNIa++PdtZLo2AQUpc1YnSU= +google.golang.org/grpc v1.52.1/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/log/logger.go new/fortio-1.40.0/log/logger.go --- old/fortio-1.39.1/log/logger.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/log/logger.go 2023-01-25 17:39:53.000000000 +0100 @@ -51,6 +51,8 @@ LogFileAndLine = flag.Bool("logcaller", true, "Logs filename and line number of callers to log") levelInternal int32 fatalPanics = flag.Bool("logfatalpanics", true, "If true, log.Fatal will panic (stack trace) instead of just exit 1") + // Tests can override this to cover exit case. + FatalExit = os.Exit ) // ChangeFlagsDefault sets some flags to a different default. @@ -192,6 +194,7 @@ // Logf logs with format at the given level. // 2 level of calls so it's always same depth for extracting caller file/line. +// Note that log.Logf(Fatal, "...") will not panic or exit, only log.Fatalf() does. func Logf(lvl Level, format string, rest ...interface{}) { logPrintf(lvl, format, rest...) } @@ -207,12 +210,6 @@ } else { log.Print(levelToStrA[lvl][0:1], " ", *LogPrefix, fmt.Sprintf(format, rest...)) } - if lvl == Fatal { - if *fatalPanics { - panic("aborting...") - } - os.Exit(1) - } } // Printf forwards to the underlying go logger to print (with only timestamp prefixing). @@ -262,9 +259,25 @@ logPrintf(Critical, format, rest...) } -// Fatalf logs if Warning level is on. +// Fatalf logs if Warning level is on and panics or exits. func Fatalf(format string, rest ...interface{}) { logPrintf(Fatal, format, rest...) + if *fatalPanics { + panic("aborting...") + } + FatalExit(1) +} + +// FErrF logs a fatal error and returns 1. +// meant for cli main functions written like: +// func main() { os.Exit(Main()) } +// and +// if err != nil { return log.FErrf("error: %v", err) } +// so they can be tested with testscript. +// See https://github.com/fortio/delta/ for example. +func FErrf(format string, rest ...interface{}) int { + logPrintf(Fatal, format, rest...) + return 1 } // LogDebug shortcut for fortio.Log(fortio.Debug). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/log/logger_test.go new/fortio-1.40.0/log/logger_test.go --- old/fortio-1.39.1/log/logger_test.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/log/logger_test.go 2023-01-25 17:39:53.000000000 +0100 @@ -129,6 +129,11 @@ expected += "C testing crit 7\n" Printf("Printf should always show n=%d", 8) expected += "Printf should always show n=8\n" + r := FErrf("FErrf should always show but not exit, n=%d", 9) + expected += "F FErrf should always show but not exit, n=9\n" + if r != 1 { + t.Errorf("FErrf returned %d instead of 1", r) + } _ = w.Flush() actual := b.String() if actual != expected { @@ -184,6 +189,18 @@ t.Fatalf("process ran with err %v, want exit status 1", err) } +func TestLoggerFatalExitOverride(t *testing.T) { + SetFlagDefaultsForClientTools() + exitCalled := false + FatalExit = func(code int) { + exitCalled = true + } + Fatalf("testing log.Fatalf exit case") + if !exitCalled { + t.Error("expected exit function override not called") + } +} + func BenchmarkLogDirect1(b *testing.B) { setLevel(Error) for n := 0; n < b.N; n++ { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/rapi/restHandler.go new/fortio-1.40.0/rapi/restHandler.go --- old/fortio-1.39.1/rapi/restHandler.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/rapi/restHandler.go 2023-01-25 17:39:53.000000000 +0100 @@ -224,6 +224,7 @@ uniform := (FormValue(r, jd, "uniform") == "on") nocatchup := (FormValue(r, jd, "nocatchup") == "on") stdClient := (FormValue(r, jd, "stdclient") == "on") + h2 := (FormValue(r, jd, "h2") == "on") sequentialWarmup := (FormValue(r, jd, "sequential-warmup") == "on") httpsInsecure := (FormValue(r, jd, "https-insecure") == "on") resolve := FormValue(r, jd, "resolve") @@ -274,6 +275,7 @@ httpopts.SequentialWarmup = sequentialWarmup httpopts.Insecure = httpsInsecure httpopts.Resolve = resolve + httpopts.H2 = h2 // Set the connection reuse range. err = bincommon.ConnectionReuseRange. WithValidator(bincommon.ConnectionReuseRangeValidator(httpopts)). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/ui/templates/main.html new/fortio-1.40.0/ui/templates/main.html --- old/fortio-1.39.1/ui/templates/main.html 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/ui/templates/main.html 2023-01-25 17:39:53.000000000 +0100 @@ -62,6 +62,7 @@ tcp/udp/http: <input type="radio" name="runner" value="http/tcp/udp" checked/> (https insecure:<input type="checkbox" name="https-insecure" />, standard go client instead of fastclient:<input type="checkbox" name="stdclient"/>, + h2: <input type="checkbox" name="h2"/>, sequential warmup: <input type="checkbox" name="sequential-warmup"/>, resolve: <input type="text" name="resolve" size="12" value="" />) <br /> or<br /> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.39.1/ui/uihandler.go new/fortio-1.40.0/ui/uihandler.go --- old/fortio-1.39.1/ui/uihandler.go 2023-01-17 19:22:12.000000000 +0100 +++ new/fortio-1.40.0/ui/uihandler.go 2023-01-25 17:39:53.000000000 +0100 @@ -133,6 +133,7 @@ uniform := (r.FormValue("uniform") == "on") nocatchup := (r.FormValue("nocatchup") == "on") stdClient := (r.FormValue("stdclient") == "on") + h2 := (r.FormValue("h2") == "on") sequentialWarmup := (r.FormValue("sequential-warmup") == "on") httpsInsecure := (r.FormValue("https-insecure") == "on") resolve := r.FormValue("resolve") @@ -191,6 +192,7 @@ httpopts.SequentialWarmup = sequentialWarmup httpopts.Insecure = httpsInsecure httpopts.Resolve = resolve + httpopts.H2 = h2 // Set the connection reuse range. err := bincommon.ConnectionReuseRange. WithValidator(bincommon.ConnectionReuseRangeValidator(httpopts)). @@ -665,7 +667,9 @@ // (be a 'directory' path). Returns true if server is started successfully. func Serve(hook bincommon.FortioHook, baseurl, port, debugpath, uipath, datadir string, percentileList []float64) bool { startTime = time.Now() - mux, addr := fhttp.Serve(port, debugpath) + // Kinda ugly that we get most params past in but we get the tls stuff from flags directly, + // it avoids making an already too long list of string params longer. probably should make a FortioConfig struct. + mux, addr := fhttp.ServeTLS(port, debugpath, *bincommon.CertFlag, *bincommon.KeyFlag) if addr == nil { return false // Error already logged } ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/google.golang.org/grpc/balancer/grpclb/grpclbstate/state.go new/vendor/google.golang.org/grpc/balancer/grpclb/grpclbstate/state.go --- old/vendor/google.golang.org/grpc/balancer/grpclb/grpclbstate/state.go 2023-01-20 10:55:48.000000000 +0100 +++ new/vendor/google.golang.org/grpc/balancer/grpclb/grpclbstate/state.go 1970-01-01 01:00:00.000000000 +0100 @@ -1,51 +0,0 @@ -/* - * - * Copyright 2020 gRPC 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 grpclbstate declares grpclb types to be set by resolvers wishing to -// pass information to grpclb via resolver.State Attributes. -package grpclbstate - -import ( - "google.golang.org/grpc/resolver" -) - -// keyType is the key to use for storing State in Attributes. -type keyType string - -const key = keyType("grpc.grpclb.grpclbstate") - -// State contains gRPCLB-relevant data passed from the name resolver. -type State struct { - // BalancerAddresses contains the remote load balancer address(es). If - // set, overrides any resolver-provided addresses with Type of GRPCLB. - BalancerAddresses []resolver.Address -} - -// Set returns a copy of the provided state with attributes containing s. s's -// data should not be mutated after calling Set. -func Set(state resolver.State, s *State) resolver.State { - state.Attributes = state.Attributes.WithValue(key, s) - return state -} - -// Get returns the grpclb State in the resolver.State, or nil if not present. -// The returned data should not be mutated. -func Get(state resolver.State) *State { - s, _ := state.Attributes.Value(key).(*State) - return s -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/google.golang.org/grpc/balancer/grpclb/state/state.go new/vendor/google.golang.org/grpc/balancer/grpclb/state/state.go --- old/vendor/google.golang.org/grpc/balancer/grpclb/state/state.go 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/google.golang.org/grpc/balancer/grpclb/state/state.go 2023-01-26 07:37:46.000000000 +0100 @@ -0,0 +1,51 @@ +/* + * + * Copyright 2020 gRPC 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 state declares grpclb types to be set by resolvers wishing to pass +// information to grpclb via resolver.State Attributes. +package state + +import ( + "google.golang.org/grpc/resolver" +) + +// keyType is the key to use for storing State in Attributes. +type keyType string + +const key = keyType("grpc.grpclb.state") + +// State contains gRPCLB-relevant data passed from the name resolver. +type State struct { + // BalancerAddresses contains the remote load balancer address(es). If + // set, overrides any resolver-provided addresses with Type of GRPCLB. + BalancerAddresses []resolver.Address +} + +// Set returns a copy of the provided state with attributes containing s. s's +// data should not be mutated after calling Set. +func Set(state resolver.State, s *State) resolver.State { + state.Attributes = state.Attributes.WithValue(key, s) + return state +} + +// Get returns the grpclb State in the resolver.State, or nil if not present. +// The returned data should not be mutated. +func Get(state resolver.State) *State { + s, _ := state.Attributes.Value(key).(*State) + return s +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go new/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go --- old/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go 2023-01-20 10:55:48.000000000 +0100 +++ new/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go 2023-01-26 07:37:46.000000000 +0100 @@ -32,7 +32,7 @@ "sync" "time" - grpclbstate "google.golang.org/grpc/balancer/grpclb/grpclbstate" + grpclbstate "google.golang.org/grpc/balancer/grpclb/state" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/internal/backoff" "google.golang.org/grpc/internal/envconfig" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/google.golang.org/grpc/version.go new/vendor/google.golang.org/grpc/version.go --- old/vendor/google.golang.org/grpc/version.go 2023-01-20 10:55:48.000000000 +0100 +++ new/vendor/google.golang.org/grpc/version.go 2023-01-26 07:37:46.000000000 +0100 @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.52.0" +const Version = "1.52.1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2023-01-20 10:55:48.000000000 +0100 +++ new/vendor/modules.txt 2023-01-26 07:37:46.000000000 +0100 @@ -42,14 +42,14 @@ # google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 ## explicit; go 1.19 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.52.0 +# google.golang.org/grpc v1.52.1 ## explicit; go 1.17 google.golang.org/grpc google.golang.org/grpc/attributes google.golang.org/grpc/backoff google.golang.org/grpc/balancer google.golang.org/grpc/balancer/base -google.golang.org/grpc/balancer/grpclb/grpclbstate +google.golang.org/grpc/balancer/grpclb/state google.golang.org/grpc/balancer/roundrobin google.golang.org/grpc/binarylog/grpc_binarylog_v1 google.golang.org/grpc/channelz