Repository: istio/fortio
Pull request #155 (2018-02-24 11:58:28)

Port 0 support is added to fhttp serve
Todo is done "// TODO: make it work for port 0 and return the port found and also
// add a non blocking mode that makes sure the socket exists before returning"

codecov[bot]: # [Codecov](https://codecov.io/gh/istio/fortio/pull/155?src=pr&el=h1) Report
> Merging [#155](https://codecov.io/gh/istio/fortio/pull/155?src=pr&el=desc) into [master](https://codecov.io/gh/istio/fortio/commit/eb049a0ca0119eca8ce0a39f482e675f10c3518f?src=pr&el=desc) will **increase** coverage by `0.3%`.
> The diff coverage is `69.2%`.

[![Impacted file tree graph](https://codecov.io/gh/istio/fortio/pull/155/graphs/tree.svg?token=6HLno2jpvU&src=pr&width=650&height=150)](https://codecov.io/gh/istio/fortio/pull/155?src=pr&el=tree)

```diff
@@           Coverage Diff            @@
##           master    #155     +/-   ##
========================================
+ Coverage      88%   88.3%   +0.3%     
========================================
  Files           7       7             
  Lines        1500    1483     -17     
========================================
- Hits         1320    1310     -10     
+ Misses        120     115      -5     
+ Partials       60      58      -2
```


| [Impacted Files](https://codecov.io/gh/istio/fortio/pull/155?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [fhttp/http.go](https://codecov.io/gh/istio/fortio/pull/155/diff?src=pr&el=tree#diff-Zmh0dHAvaHR0cC5nbw==) | `81% <69.2%> (-0.1%)` | :arrow_down: |
| [fgrpc/grpcrunner.go](https://codecov.io/gh/istio/fortio/pull/155/diff?src=pr&el=tree#diff-ZmdycGMvZ3JwY3J1bm5lci5nbw==) | `77.8% <0%> (+5.1%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/istio/fortio/pull/155?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/istio/fortio/pull/155?src=pr&el=footer). Last update [eb049a0...ee6d47a](https://codecov.io/gh/istio/fortio/pull/155?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/echosrv/echo.go b/echosrv/echo.go
index bf3cf76..3f3068c 100644
--- a/echosrv/echo.go
+++ b/echosrv/echo.go
@@ -23,7 +23,6 @@ import (
 	"flag"
 
 	"istio.io/fortio/fhttp"
-	"istio.io/fortio/fnet"
 )
 
 var (
@@ -33,6 +32,5 @@ var (
 
 func main() {
 	flag.Parse()
-	httpPort := fnet.NormalizePort(*port)
-	fhttp.Serve(httpPort, *debugPath)
+	fhttp.Serve(*port, *debugPath)
 }
diff --git a/fhttp/http.go b/fhttp/http.go
index 0f57110..c927baf 100644
--- a/fhttp/http.go
+++ b/fhttp/http.go
@@ -1276,17 +1276,24 @@ func DebugHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 // Serve starts a debug / echo http server on the given port.
-// TODO: make it work for port 0 and return the port found and also
-// add a non blocking mode that makes sure the socket exists before returning
-func Serve(port, debugPath string) {
+// Returns the port that opened for listing socket
+func Serve(port, debugPath string) int {
 	startTime = time.Now()
 	nPort := fnet.NormalizePort(port)
-	fmt.Printf("Fortio %s echo server listening on port %s\n", version.Short(), nPort)
-	if debugPath != "" {
-		http.HandleFunc(debugPath, DebugHandler)
-	}
-	http.HandleFunc("/", EchoHandler)
-	if err := http.ListenAndServe(nPort, nil); err != nil {
-		fmt.Println("Error starting server", err)
+	listener, err := net.Listen("tcp", nPort)
+	if err != nil {
+		log.Fatalf("Error occurred while listening %v: %v", nPort, err)
 	}
+	portValue := listener.Addr().(*net.TCPAddr).Port
+	fmt.Printf("Fortio %s echo server listening on port %d\n", version.Short(), portValue)
+	go func() {
+		if debugPath != "" {
+			http.HandleFunc(debugPath, DebugHandler)
+		}
+		http.HandleFunc("/", EchoHandler)
+		if err := http.Serve(listener, nil); err != nil {
+			fmt.Println("Error starting server", err)
+		}
+	}()
+	return portValue
 }


Test patch:
diff --git a/fhttp/httprunner_test.go b/fhttp/httprunner_test.go
index c04c325..970fa4c 100644
--- a/fhttp/httprunner_test.go
+++ b/fhttp/httprunner_test.go
@@ -21,9 +21,7 @@ package fhttp
 
 import (
 	"fmt"
-	"net"
 	"net/http"
-	"strconv"
 	"strings"
 	"testing"
 	"time"
@@ -116,17 +114,12 @@ func TestHTTPRunnerBadServer(t *testing.T) {
 // the error test for / url above fail:
 
 func TestServe(t *testing.T) {
-	listener, err := net.Listen("tcp", ":0") // nolint: gas
-	if err != nil {
-		log.Fatalf("Unable to listen to dynamic port: %v", err)
-	}
-	port := listener.Addr().(*net.TCPAddr).Port
+	port := Serve("0", "/debugx1")
 	log.Infof("Using port: %d", port)
-	listener.Close()
 	url := fmt.Sprintf("http://localhost:%d/debugx1?env=dump", port)
-	go func() {
-		Serve(strconv.Itoa(port), "/debugx1")
-	}()
+	if port == 0 {
+		t.Errorf("outport: %d must be different", port)
+	}
 	time.Sleep(100 * time.Millisecond)
 	o := NewHTTPOptions(url)
 	o.AddAndValidateExtraHeader("X-Header: value1")