Adding return error value to checkPortAvailability to enable testing of function. Adding checkport_test.go to test checkPortAvailability. Updated server-main.go to use error value from checkPortAvailability and calls fatalIf if an error is returned. (#2322)

This commit is contained in:
Jesse Lucas 2016-07-29 17:05:31 -04:00 committed by Harshavardhana
parent cf9ba7b88f
commit 851d05161a
3 changed files with 76 additions and 12 deletions

View file

@ -18,6 +18,7 @@ package main
import (
"errors"
"fmt"
"net"
"os"
"syscall"
@ -32,7 +33,7 @@ import (
// This causes confusion on Mac OSX that minio server is not reachable
// on 127.0.0.1 even though minio server is running. So before we start
// the minio server we make sure that the port is free on all the IPs.
func checkPortAvailability(port int) {
func checkPortAvailability(port int) error {
isAddrInUse := func(err error) bool {
// Check if the syscall error is EADDRINUSE.
// EADDRINUSE is the system call error if another process is
@ -54,40 +55,48 @@ func checkPortAvailability(port int) {
}
return true
}
ifcs, err := net.Interfaces()
if err != nil {
fatalIf(err, "Unable to list interfaces.")
return err
}
for _, ifc := range ifcs {
addrs, err := ifc.Addrs()
if err != nil {
fatalIf(err, "Unable to list addresses on interface %s.", ifc.Name)
return err
}
for _, addr := range addrs {
ipnet, ok := addr.(*net.IPNet)
if !ok {
errorIf(errors.New(""), "Failed to assert type on (*net.IPNet) interface.")
continue
}
ip := ipnet.IP
network := "tcp4"
if ip.To4() == nil {
network = "tcp6"
}
tcpAddr := net.TCPAddr{IP: ip, Port: port, Zone: ifc.Name}
l, err := net.ListenTCP(network, &tcpAddr)
l, err := net.Listen(network, fmt.Sprintf(":%d", port))
if err != nil {
if isAddrInUse(err) {
// Fail if port is already in use.
fatalIf(err, "Unable to listen on %s:%.d.", tcpAddr.IP, tcpAddr.Port)
} else {
// Ignore other errors.
continue
return err
}
// Ignore other errors.
continue
}
if err = l.Close(); err != nil {
fatalIf(err, "Unable to close listener on %s:%.d.", tcpAddr.IP, tcpAddr.Port)
return err
}
}
}
return nil
}

54
checkport_test.go Normal file
View file

@ -0,0 +1,54 @@
/*
* Minio Cloud Storage, (C) 2016 Minio, Inc.
*
* 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 main
import (
"fmt"
"net"
"runtime"
"testing"
)
func TestCheckPortAvailability(t *testing.T) {
tests := []struct {
port int
}{
{9000},
{10000},
}
for _, test := range tests {
// This test should pass if the ports are available
err := checkPortAvailability(test.port)
if err != nil {
t.Fatalf("checkPortAvailability test failed for port: %d. Error: %v", test.port, err)
}
// Now use the ports and check again
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", test.port))
if err != nil {
t.Fail()
}
defer ln.Close()
err = checkPortAvailability(test.port)
// Skip if the os is windows due to https://github.com/golang/go/issues/7598
if err == nil && runtime.GOOS != "windows" {
t.Fatalf("checkPortAvailability should fail for port: %d. Error: %v", test.port, err)
}
}
}

View file

@ -246,7 +246,9 @@ func serverMain(c *cli.Context) {
serverAddress := c.String("address")
// Check if requested port is available.
checkPortAvailability(getPort(serverAddress))
port := getPort(serverAddress)
err := checkPortAvailability(port)
fatalIf(err, "Port unavailable %d", port)
// Disks to be ignored in server init, to skip format healing.
ignoredDisks := strings.Split(c.String("ignore-disks"), ",")
@ -268,7 +270,6 @@ func serverMain(c *cli.Context) {
printStartupMessage(endPoints)
// Start server.
var err error
// Configure TLS if certs are available.
if tls {
err = apiServer.ListenAndServeTLS(mustGetCertFile(), mustGetKeyFile())