<commit_before>package utils

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"testing"
	"text/template"
	"time"

	"github.com/ThomasRooney/gexpect"
)

// Deis points to the CLI used to run tests.
var Deis = "deis "

// DeisTestConfig allows tests to be repeated against different
// targets, with different example apps, using specific credentials, and so on.
type DeisTestConfig struct {
	AuthKey     string
	Hosts       string
	Domain      string
	SSHKey      string
	ClusterName string
	UserName    string
	Password    string
	Email       string
	ExampleApp  string
	AppName     string
	ProcessNum  string
	ImageID     string
	Version     string
	AppUser     string
}

// randomApp is used for the test run if DEIS_TEST_APP isn't set
var randomApp = GetRandomApp()

// GetGlobalConfig returns a test configuration object.
func GetGlobalConfig() *DeisTestConfig {
	authKey := os.Getenv("DEIS_TEST_AUTH_KEY")
	if authKey == "" {
		authKey = "deis"
	}
	hosts := os.Getenv("DEIS_TEST_HOSTS")
	if hosts == "" {
		hosts = "172.17.8.100"
	}
	domain := os.Getenv("DEIS_TEST_DOMAIN")
	if domain == "" {
		domain = "local.deisapp.com"
	}
	sshKey := os.Getenv("DEIS_TEST_SSH_KEY")
	if sshKey == "" {
		sshKey = "~/.vagrant.d/insecure_private_key"
	}
	exampleApp := os.Getenv("DEIS_TEST_APP")
	if exampleApp == "" {
		exampleApp = randomApp
	}
	var envCfg = DeisTestConfig{
		AuthKey:     authKey,
		Hosts:       hosts,
		Domain:      domain,
		SSHKey:      sshKey,
		ClusterName: "dev",
		UserName:    "test",
		Password:    "asdf1234",
		Email:       "test@test.co.nz",
		ExampleApp:  exampleApp,
		AppName:     "sample",
		ProcessNum:  "2",
		ImageID:     "buildtest",
		Version:     "2",
		AppUser:     "test1",
	}
	return &envCfg
}

func doCurl(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)

	if !strings.Contains(string(body), "Powered by") {
		return nil, fmt.Errorf("App not started (%d)\nBody: (%s)", response.StatusCode, string(body))
	}

	return body, nil
}

// Curl connects to a Deis endpoint to see if the example app is running.
func Curl(t *testing.T, params *DeisTestConfig) {
	CurlWithFail(t, params, false, "")
}

// CurlWithFail connects to a Deis endpoint to see if the example app is running.
func CurlWithFail(t *testing.T, params *DeisTestConfig, failFlag bool, expect string) {
	url := "http://" + params.AppName + "." + params.Domain

	// FIXME: try the curl a few times
	for i := 0; i < 20; i++ {
		body, err := doCurl(url)
		if err == nil {
			fmt.Println(string(body))
			return
		}
		time.Sleep(1 * time.Second)
	}

	// once more to fail with an error
	body, err := doCurl(url)

	switch failFlag {
	case true:
		if err != nil {
			if strings.Contains(string(err.Error()), expect) {
				fmt.Println("(Error expected...ok) " + expect)
			} else {
				t.Fatal(err)
			}
		} else {
			if strings.Contains(string(body), expect) {
				fmt.Println("(Error expected...ok) " + expect)
			} else {
				t.Fatal(err)
			}
		}
	case false:
		if err != nil {
			t.Fatal(err)
		} else {
			fmt.Println(string(body))
		}
	}
}

// AuthCancel tests whether `deis auth:cancel` destroys a user's account.
func AuthCancel(t *testing.T, params *DeisTestConfig) {
	fmt.Println("deis auth:cancel")
	child, err := gexpect.Spawn(Deis + " auth:cancel")
	if err != nil {
		t.Fatalf("command not started\n%v", err)
	}
	fmt.Println("username:")
	err = child.Expect("username:")
	if err != nil {
		t.Fatalf("expect username failed\n%v", err)
	}
	child.SendLine(params.UserName)
	fmt.Print("password:")
	err = child.Expect("password:")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(params.Password)
	err = child.ExpectRegex("(y/n)")
	if err != nil {
		t.Fatalf("expect cancel \n%v", err)
	}
	child.SendLine("y")
	err = child.Expect("Account cancelled")
	if err != nil {
		t.Fatalf("command executiuon failed\n%v", err)
	}
	child.Close()
}

// AuthPasswd tests whether `deis auth:passwd` updates a user's password.
func AuthPasswd(t *testing.T, params *DeisTestConfig, password string) {
	fmt.Println("deis auth:passwd")
	child, err := gexpect.Spawn(Deis + " auth:passwd")
	if err != nil {
		t.Fatalf("command not started\n%v", err)
	}
	fmt.Println("current password:")
	err = child.Expect("current password: ")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(params.Password)
	fmt.Println("new password:")
	err = child.Expect("new password: ")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(password)
	fmt.Println("new password (confirm):")
	err = child.Expect("new password (confirm): ")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(password)
	err = child.Expect("Password change succeeded")
	if err != nil {
		t.Fatalf("command executiuon failed\n%v", err)
	}
	child.Close()
}

// CheckList executes a command and optionally tests whether its output does
// or does not contain a given string.
func CheckList(
	t *testing.T, cmd string, params interface{}, contain string, notflag bool) {
	var cmdBuf bytes.Buffer
	tmpl := template.Must(template.New("cmd").Parse(cmd))
	if err := tmpl.Execute(&cmdBuf, params); err != nil {
		t.Fatal(err)
	}
	cmdString := cmdBuf.String()
	fmt.Println(cmdString)
	var cmdl *exec.Cmd
	if strings.Contains(cmd, "cat") {
		cmdl = exec.Command("sh", "-c", cmdString)
	} else {
		cmdl = exec.Command("sh", "-c", Deis+cmdString)
	}
	stdout, _, err := RunCommandWithStdoutStderr(cmdl)
	if err != nil {
		t.Fatal(err)
	}
	if strings.Contains(stdout.String(), contain) == notflag {
		if notflag {
			t.Fatalf(
				"Didn't expect '%s' in command output:\n%v", contain, stdout)
		}
		t.Fatalf("Expected '%s' in command output:\n%v", contain, stdout)
	}
}

// Execute takes command string and parameters required to execute the command,
// a failflag to check whether the command is expected to fail, and an expect
// string to check whether the command has failed according to failflag.
//
// If failflag is true and the command failed, check the stdout and stderr for
// the expect string.
func Execute(t *testing.T, cmd string, params interface{}, failFlag bool, expect string) {
	var cmdBuf bytes.Buffer
	tmpl := template.Must(template.New("cmd").Parse(cmd))
	if err := tmpl.Execute(&cmdBuf, params); err != nil {
		t.Fatal(err)
	}
	cmdString := cmdBuf.String()
	fmt.Println(cmdString)
	var cmdl *exec.Cmd
	if strings.Contains(cmd, "git") {
		cmdl = exec.Command("sh", "-c", cmdString)
	} else {
		cmdl = exec.Command("sh", "-c", Deis+cmdString)
	}

	switch failFlag {
	case true:
		if stdout, stderr, err := RunCommandWithStdoutStderr(cmdl); err != nil {
			if strings.Contains(stdout.String(), expect) || strings.Contains(stderr.String(), expect) {
				fmt.Println("(Error expected...ok)")
			} else {
				t.Fatal(err)
			}
		} else {
			if strings.Contains(stdout.String(), expect) || strings.Contains(stderr.String(), expect) {
				fmt.Println("(Error expected...ok)" + expect)
			} else {
				t.Fatal(err)
			}
		}
	case false:
		if _, _, err := RunCommandWithStdoutStderr(cmdl); err != nil {
			t.Fatal(err)
		} else {
			fmt.Println("ok")
		}
	}
}

// AppsDestroyTest destroys a Deis app and checks that it was successful.
func AppsDestroyTest(t *testing.T, params *DeisTestConfig) {
	cmd := "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
	if err := Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	Execute(t, cmd, params, false, "")
	if err := Chdir(".."); err != nil {
		t.Fatal(err)
	}
	if err := Rmdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
}

// GetRandomApp returns a known working example app at random for testing.
func GetRandomApp() string {
	rand.Seed(int64(time.Now().Unix()))
	apps := []string{
		"example-clojure-ring",
		// "example-dart",
		"example-dockerfile-python",
		"example-go",
		"example-java-jetty",
		"example-nodejs-express",
		// "example-php",
		"example-play",
		"example-python-django",
		"example-python-flask",
		"example-ruby-sinatra",
		"example-scala",
		"example-dockerfile-http",
	}
	return apps[rand.Intn(len(apps))]
}
<commit_msg>fix(tests): check for expected prompt<commit_after>package utils

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"testing"
	"text/template"
	"time"

	"github.com/ThomasRooney/gexpect"
)

// Deis points to the CLI used to run tests.
var Deis = "deis "

// DeisTestConfig allows tests to be repeated against different
// targets, with different example apps, using specific credentials, and so on.
type DeisTestConfig struct {
	AuthKey     string
	Hosts       string
	Domain      string
	SSHKey      string
	ClusterName string
	UserName    string
	Password    string
	Email       string
	ExampleApp  string
	AppName     string
	ProcessNum  string
	ImageID     string
	Version     string
	AppUser     string
}

// randomApp is used for the test run if DEIS_TEST_APP isn't set
var randomApp = GetRandomApp()

// GetGlobalConfig returns a test configuration object.
func GetGlobalConfig() *DeisTestConfig {
	authKey := os.Getenv("DEIS_TEST_AUTH_KEY")
	if authKey == "" {
		authKey = "deis"
	}
	hosts := os.Getenv("DEIS_TEST_HOSTS")
	if hosts == "" {
		hosts = "172.17.8.100"
	}
	domain := os.Getenv("DEIS_TEST_DOMAIN")
	if domain == "" {
		domain = "local.deisapp.com"
	}
	sshKey := os.Getenv("DEIS_TEST_SSH_KEY")
	if sshKey == "" {
		sshKey = "~/.vagrant.d/insecure_private_key"
	}
	exampleApp := os.Getenv("DEIS_TEST_APP")
	if exampleApp == "" {
		exampleApp = randomApp
	}
	var envCfg = DeisTestConfig{
		AuthKey:     authKey,
		Hosts:       hosts,
		Domain:      domain,
		SSHKey:      sshKey,
		ClusterName: "dev",
		UserName:    "test",
		Password:    "asdf1234",
		Email:       "test@test.co.nz",
		ExampleApp:  exampleApp,
		AppName:     "sample",
		ProcessNum:  "2",
		ImageID:     "buildtest",
		Version:     "2",
		AppUser:     "test1",
	}
	return &envCfg
}

func doCurl(url string) ([]byte, error) {
	response, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)

	if !strings.Contains(string(body), "Powered by") {
		return nil, fmt.Errorf("App not started (%d)\nBody: (%s)", response.StatusCode, string(body))
	}

	return body, nil
}

// Curl connects to a Deis endpoint to see if the example app is running.
func Curl(t *testing.T, params *DeisTestConfig) {
	CurlWithFail(t, params, false, "")
}

// CurlWithFail connects to a Deis endpoint to see if the example app is running.
func CurlWithFail(t *testing.T, params *DeisTestConfig, failFlag bool, expect string) {
	url := "http://" + params.AppName + "." + params.Domain

	// FIXME: try the curl a few times
	for i := 0; i < 20; i++ {
		body, err := doCurl(url)
		if err == nil {
			fmt.Println(string(body))
			return
		}
		time.Sleep(1 * time.Second)
	}

	// once more to fail with an error
	body, err := doCurl(url)

	switch failFlag {
	case true:
		if err != nil {
			if strings.Contains(string(err.Error()), expect) {
				fmt.Println("(Error expected...ok) " + expect)
			} else {
				t.Fatal(err)
			}
		} else {
			if strings.Contains(string(body), expect) {
				fmt.Println("(Error expected...ok) " + expect)
			} else {
				t.Fatal(err)
			}
		}
	case false:
		if err != nil {
			t.Fatal(err)
		} else {
			fmt.Println(string(body))
		}
	}
}

// AuthCancel tests whether `deis auth:cancel` destroys a user's account.
func AuthCancel(t *testing.T, params *DeisTestConfig) {
	fmt.Println("deis auth:cancel")
	child, err := gexpect.Spawn(Deis + " auth:cancel")
	if err != nil {
		t.Fatalf("command not started\n%v", err)
	}
	fmt.Println("username:")
	err = child.Expect("username:")
	if err != nil {
		t.Fatalf("expect username failed\n%v", err)
	}
	child.SendLine(params.UserName)
	fmt.Print("password:")
	err = child.Expect("password:")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(params.Password)
	err = child.ExpectRegex("(y/N)")
	if err != nil {
		t.Fatalf("expect cancel \n%v", err)
	}
	child.SendLine("y")
	err = child.Expect("Account cancelled")
	if err != nil {
		t.Fatalf("command executiuon failed\n%v", err)
	}
	child.Close()
}

// AuthPasswd tests whether `deis auth:passwd` updates a user's password.
func AuthPasswd(t *testing.T, params *DeisTestConfig, password string) {
	fmt.Println("deis auth:passwd")
	child, err := gexpect.Spawn(Deis + " auth:passwd")
	if err != nil {
		t.Fatalf("command not started\n%v", err)
	}
	fmt.Println("current password:")
	err = child.Expect("current password: ")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(params.Password)
	fmt.Println("new password:")
	err = child.Expect("new password: ")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(password)
	fmt.Println("new password (confirm):")
	err = child.Expect("new password (confirm): ")
	if err != nil {
		t.Fatalf("expect password failed\n%v", err)
	}
	child.SendLine(password)
	err = child.Expect("Password change succeeded")
	if err != nil {
		t.Fatalf("command executiuon failed\n%v", err)
	}
	child.Close()
}

// CheckList executes a command and optionally tests whether its output does
// or does not contain a given string.
func CheckList(
	t *testing.T, cmd string, params interface{}, contain string, notflag bool) {
	var cmdBuf bytes.Buffer
	tmpl := template.Must(template.New("cmd").Parse(cmd))
	if err := tmpl.Execute(&cmdBuf, params); err != nil {
		t.Fatal(err)
	}
	cmdString := cmdBuf.String()
	fmt.Println(cmdString)
	var cmdl *exec.Cmd
	if strings.Contains(cmd, "cat") {
		cmdl = exec.Command("sh", "-c", cmdString)
	} else {
		cmdl = exec.Command("sh", "-c", Deis+cmdString)
	}
	stdout, _, err := RunCommandWithStdoutStderr(cmdl)
	if err != nil {
		t.Fatal(err)
	}
	if strings.Contains(stdout.String(), contain) == notflag {
		if notflag {
			t.Fatalf(
				"Didn't expect '%s' in command output:\n%v", contain, stdout)
		}
		t.Fatalf("Expected '%s' in command output:\n%v", contain, stdout)
	}
}

// Execute takes command string and parameters required to execute the command,
// a failflag to check whether the command is expected to fail, and an expect
// string to check whether the command has failed according to failflag.
//
// If failflag is true and the command failed, check the stdout and stderr for
// the expect string.
func Execute(t *testing.T, cmd string, params interface{}, failFlag bool, expect string) {
	var cmdBuf bytes.Buffer
	tmpl := template.Must(template.New("cmd").Parse(cmd))
	if err := tmpl.Execute(&cmdBuf, params); err != nil {
		t.Fatal(err)
	}
	cmdString := cmdBuf.String()
	fmt.Println(cmdString)
	var cmdl *exec.Cmd
	if strings.Contains(cmd, "git") {
		cmdl = exec.Command("sh", "-c", cmdString)
	} else {
		cmdl = exec.Command("sh", "-c", Deis+cmdString)
	}

	switch failFlag {
	case true:
		if stdout, stderr, err := RunCommandWithStdoutStderr(cmdl); err != nil {
			if strings.Contains(stdout.String(), expect) || strings.Contains(stderr.String(), expect) {
				fmt.Println("(Error expected...ok)")
			} else {
				t.Fatal(err)
			}
		} else {
			if strings.Contains(stdout.String(), expect) || strings.Contains(stderr.String(), expect) {
				fmt.Println("(Error expected...ok)" + expect)
			} else {
				t.Fatal(err)
			}
		}
	case false:
		if _, _, err := RunCommandWithStdoutStderr(cmdl); err != nil {
			t.Fatal(err)
		} else {
			fmt.Println("ok")
		}
	}
}

// AppsDestroyTest destroys a Deis app and checks that it was successful.
func AppsDestroyTest(t *testing.T, params *DeisTestConfig) {
	cmd := "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
	if err := Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	Execute(t, cmd, params, false, "")
	if err := Chdir(".."); err != nil {
		t.Fatal(err)
	}
	if err := Rmdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
}

// GetRandomApp returns a known working example app at random for testing.
func GetRandomApp() string {
	rand.Seed(int64(time.Now().Unix()))
	apps := []string{
		"example-clojure-ring",
		// "example-dart",
		"example-dockerfile-python",
		"example-go",
		"example-java-jetty",
		"example-nodejs-express",
		// "example-php",
		"example-play",
		"example-python-django",
		"example-python-flask",
		"example-ruby-sinatra",
		"example-scala",
		"example-dockerfile-http",
	}
	return apps[rand.Intn(len(apps))]
}
<|endoftext|>


<commit_before>package search_test

import (
	"github.com/gonum/graph/concrete"
	"github.com/gonum/graph/search"
	"math"
	"testing"
)

func TestFWOneEdge(t *testing.T) {
	dg := concrete.NewDenseGraph(2, true)
	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(paths) != 1 {
		t.Errorf("Didn't get right paths in FW %v", paths)
	}

	path = paths[0]
	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW allpaths %v", path)
	}
}

func TestFWTwoPaths(t *testing.T) {
	dg := concrete.NewDenseGraph(5, false)
	// Adds two paths from 0->2 of equal length
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(2), 2.0, true)
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(1), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(1), concrete.GonumNode(2), 1.0, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)
	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(2))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("Path has incorrect cost, %f", cost)
	}

	if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
		t.Logf("Got correct path: %v", path)
	} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
		t.Logf("Got correct path %v", path)
	} else {
		t.Errorf("Got wrong path %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(2))

	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("All paths function gets incorrect cost, %f", cost)
	}

	if len(paths) != 2 {
		t.Fatalf("Didn't get all shortest paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
			t.Logf("Got correct path for all paths: %v", path)
		} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
			t.Logf("Got correct path for all paths %v", path)
		} else {
			t.Errorf("Got wrong path for all paths %v", path)
		}
	}
}
<commit_msg>Made more complex FW test<commit_after>package search_test

import (
	"github.com/gonum/graph/concrete"
	"github.com/gonum/graph/search"
	"math"
	"testing"
)

func TestFWOneEdge(t *testing.T) {
	dg := concrete.NewDenseGraph(2, true)
	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(paths) != 1 {
		t.Errorf("Didn't get right paths in FW %v", paths)
	}

	path = paths[0]
	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW allpaths %v", path)
	}
}

func TestFWTwoPaths(t *testing.T) {
	dg := concrete.NewDenseGraph(5, false)
	// Adds two paths from 0->2 of equal length
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(2), 2.0, true)
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(1), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(1), concrete.GonumNode(2), 1.0, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)
	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(2))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("Path has incorrect cost, %f", cost)
	}

	if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
		t.Logf("Got correct path: %v", path)
	} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
		t.Logf("Got correct path %v", path)
	} else {
		t.Errorf("Got wrong path %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(2))

	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("All paths function gets incorrect cost, %f", cost)
	}

	if len(paths) != 2 {
		t.Fatalf("Didn't get all shortest paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
			t.Logf("Got correct path for all paths: %v", path)
		} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
			t.Logf("Got correct path for all paths %v", path)
		} else {
			t.Errorf("Got wrong path for all paths %v", path)
		}
	}
}

// Tests with multiple right paths, but also one dead-end path
// and one path that reaches the goal, but not optimally
func TestFWConfoundingPath(t *testing.T) {
	dg := concrete.NewDenseGraph(6, false)

	// Add a path from 0->5 of cost 4
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(1), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(1), concrete.GonumNode(2), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(2), concrete.GonumNode(3), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(3), concrete.GonumNode(5), 1.0, true)

	// Add direct edge to goal of cost 4
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(5), 4.0, true)

	// Add edge to 3 that's overpriced
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(3), 4.0, true)

	// Add very cheap edge to 4 which is a dead end
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(4), 0.25, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4.0) > .000001 {
		t.Error("Incorrect cost %f", cost)
	}

	if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
		t.Log("Correct path found for single path %v", path)
	} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
		t.Log("Correct path found for single path %v", path)
	} else {
		t.Error("Wrong path found for single path %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4.0) > .000001 {
		t.Error("Incorrect cost %f", cost)
	}

	if len(paths) != 2 {
		t.Error("Wrong paths gooten for all paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
			t.Log("Correct path found for all paths %v", path)
		} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
			t.Log("Correct path found for all paths %v", path)
		} else {
			t.Error("Wrong path found for all paths %v", path)
		}
	}
}
<|endoftext|>


<commit_before>package search_test

import (
	"github.com/gonum/graph/concrete"
	"github.com/gonum/graph/search"
	"math"
	"testing"
)

func TestFWOneEdge(t *testing.T) {
	dg := concrete.NewDenseGraph(2, true)
	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(paths) != 1 {
		t.Errorf("Didn't get right paths in FW %v", paths)
	}

	path = paths[0]
	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW allpaths %v", path)
	}
}

func TestFWTwoPaths(t *testing.T) {
	dg := concrete.NewDenseGraph(5, false)
	// Adds two paths from 0->2 of equal length
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(2), 2.0, true)
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(1), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(1), concrete.GonumNode(2), 1.0, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)
	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(2))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("Path has incorrect cost, %f", cost)
	}

	if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
		t.Logf("Got correct path: %v", path)
	} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
		t.Logf("Got correct path %v", path)
	} else {
		t.Errorf("Got wrong path %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(2))

	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("All paths function gets incorrect cost, %f", cost)
	}

	if len(paths) != 2 {
		t.Fatalf("Didn't get all shortest paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
			t.Logf("Got correct path for all paths: %v", path)
		} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
			t.Logf("Got correct path for all paths %v", path)
		} else {
			t.Errorf("Got wrong path for all paths %v", path)
		}
	}
}

// Tests with multiple right paths, but also one dead-end path
// and one path that reaches the goal, but not optimally
func TestFWConfoundingPath(t *testing.T) {
	dg := concrete.NewDenseGraph(6, false)

	// Add a path from 0->5 of cost 4
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(1), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(1), concrete.GonumNode(2), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(2), concrete.GonumNode(3), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(3), concrete.GonumNode(5), 1.0, true)

	// Add direct edge to goal of cost 4
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(5), 4.0, true)

	// Add edge to 3 that's overpriced
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(3), 4.0, true)

	// Add very cheap edge to 4 which is a dead end
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(4), 0.25, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4.0) > .000001 {
		t.Error("Incorrect cost %f", cost)
	}

	if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
		t.Log("Correct path found for single path %v", path)
	} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
		t.Log("Correct path found for single path %v", path)
	} else {
		t.Error("Wrong path found for single path %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4.0) > .000001 {
		t.Error("Incorrect cost %f", cost)
	}

	if len(paths) != 2 {
		t.Error("Wrong paths gooten for all paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
			t.Log("Correct path found for all paths %v", path)
		} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
			t.Log("Correct path found for all paths %v", path)
		} else {
			t.Error("Wrong path found for all paths %v", path)
		}
	}
}
<commit_msg>Added test for no path condition<commit_after>package search_test

import (
	"github.com/gonum/graph/concrete"
	"github.com/gonum/graph/search"
	"math"
	"testing"
)

func TestFWOneEdge(t *testing.T) {
	dg := concrete.NewDenseGraph(2, true)
	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1.0) > .000001 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(paths) != 1 {
		t.Errorf("Didn't get right paths in FW %v", paths)
	}

	path = paths[0]
	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW allpaths %v", path)
	}
}

func TestFWTwoPaths(t *testing.T) {
	dg := concrete.NewDenseGraph(5, false)
	// Adds two paths from 0->2 of equal length
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(2), 2.0, true)
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(1), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(1), concrete.GonumNode(2), 1.0, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)
	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(2))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("Path has incorrect cost, %f", cost)
	}

	if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
		t.Logf("Got correct path: %v", path)
	} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
		t.Logf("Got correct path %v", path)
	} else {
		t.Errorf("Got wrong path %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(2))

	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2.0) > .00001 {
		t.Errorf("All paths function gets incorrect cost, %f", cost)
	}

	if len(paths) != 2 {
		t.Fatalf("Didn't get all shortest paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
			t.Logf("Got correct path for all paths: %v", path)
		} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
			t.Logf("Got correct path for all paths %v", path)
		} else {
			t.Errorf("Got wrong path for all paths %v", path)
		}
	}
}

// Tests with multiple right paths, but also one dead-end path
// and one path that reaches the goal, but not optimally
func TestFWConfoundingPath(t *testing.T) {
	dg := concrete.NewDenseGraph(6, false)

	// Add a path from 0->5 of cost 4
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(1), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(1), concrete.GonumNode(2), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(2), concrete.GonumNode(3), 1.0, true)
	dg.SetEdgeCost(concrete.GonumNode(3), concrete.GonumNode(5), 1.0, true)

	// Add direct edge to goal of cost 4
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(5), 4.0, true)

	// Add edge to 3 that's overpriced
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(3), 4.0, true)

	// Add very cheap edge to 4 which is a dead end
	dg.SetEdgeCost(concrete.GonumNode(0), concrete.GonumNode(4), 0.25, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.GonumNode(0), concrete.GonumNode(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4.0) > .000001 {
		t.Error("Incorrect cost %f", cost)
	}

	if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
		t.Log("Correct path found for single path %v", path)
	} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
		t.Log("Correct path found for single path %v", path)
	} else {
		t.Error("Wrong path found for single path %v", path)
	}

	paths, cost, err := aPaths(concrete.GonumNode(0), concrete.GonumNode(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4.0) > .000001 {
		t.Error("Incorrect cost %f", cost)
	}

	if len(paths) != 2 {
		t.Error("Wrong paths gooten for all paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
			t.Log("Correct path found for all paths %v", path)
		} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
			t.Log("Correct path found for all paths %v", path)
		} else {
			t.Error("Wrong path found for all paths %v", path)
		}
	}

	path, _, err = sPath(concrete.GonumNode(4), concrete.GonumNode(5))
	if err != nil {
		t.Log("Success!", err)
	} else {
		t.Error("Path was found by FW single path where one shouldn't be %v", path)
	}

	paths, _, err = aPaths(concrete.GonumNode(4), concrete.GonumNode(5))
	if err != nil {
		t.Log("Success!", err)
	} else {
		t.Error("Path was found by FW multi-path where one shouldn't be %v", paths)
	}
}
<|endoftext|>


<commit_before>package acceptance_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"lib/models"
	"lib/policy_client"
	"lib/testsupport"
	"net"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"code.cloudfoundry.org/lager/lagertest"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-cf-experimental/rainmaker"
)

const Timeout_Push = 5 * time.Minute
const Timeout_Short = 10 * time.Second

var ports []int

var _ = Describe("connectivity between containers on the overlay network", func() {
	Describe("networking policy", func() {
		var (
			appProxy       string
			appRegistry    string
			appsTest       []string
			appInstances   int
			applications   int
			proxyInstances int
			prefix         string
		)

		BeforeEach(func() {
			appInstances = testConfig.AppInstances
			applications = testConfig.Applications
			proxyInstances = testConfig.ProxyInstances
			if testConfig.Prefix == "" {
				prefix = "scale-"
			} else {
				prefix = testConfig.Prefix
			}

			appProxy = prefix + "proxy"
			appRegistry = prefix + "registry"
			for i := 0; i < applications; i++ {
				appsTest = append(appsTest, fmt.Sprintf(prefix+"tick-%d", i))
			}

			ports = []int{8080}
			for i := 0; i < testConfig.ExtraListenPorts; i++ {
				ports = append(ports, 7000+i)
			}
		})

		AfterEach(func() {
			appReport(appProxy, Timeout_Short)
			appReport(appRegistry, Timeout_Short)
			appsReport(appsTest, Timeout_Short)
		})

		It("allows the user to configure policies", func(done Done) {
			if testConfig.SkipCfPush {
				AuthAsAdmin()
				Expect(cf.Cf("target", "-o", prefix+"org", "-s", prefix+"space").Wait(Timeout_Push)).To(gexec.Exit(0))
			} else {
				cmd := exec.Command("go", "run", "../cf-pusher/cmd/cf-pusher/main.go", "--config", helpers.ConfigPath())
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				fmt.Println("\n-----cf-pusher start ------")
				err := cmd.Run()
				fmt.Println("\n-----cf-pusher done -------")
				Expect(err).NotTo(HaveOccurred())
			}

			By("checking that all test app instances have registered themselves")
			checkRegistry(appRegistry, 60*time.Second, 500*time.Millisecond, len(appsTest)*appInstances)

			appIPs := getAppIPs(appRegistry)

			By("checking that the connection fails")
			runWithTimeout("check connection failures", 5*time.Minute, func() {
				assertConnectionFails(appProxy, appIPs, ports, proxyInstances)
			})

			By("creating policies")
			doAllPolicies("create", appProxy, appsTest, ports)

			// we should wait for minimum (pollInterval * 2)
			By("waiting for policies to be created on cells")
			time.Sleep(10 * time.Second)

			By(fmt.Sprintf("checking that %s can reach %s", appProxy, appsTest))
			runWithTimeout("check connection success", 5*time.Minute, func() {
				assertConnectionSucceeds(appProxy, appIPs, ports, proxyInstances)
			})

			dumpStats(appProxy, config.AppsDomain)

			By("deleting policies")
			doAllPolicies("delete", appProxy, appsTest, ports)

			By(fmt.Sprintf("checking that %s can NOT reach %s", appProxy, appsTest))
			runWithTimeout("check connection failures, again", 5*time.Minute, func() {
				assertConnectionFails(appProxy, appIPs, ports, proxyInstances)
			})

			if !testConfig.SkipCfPush {
				By("checking that the registry updates when apps are scaled")
				scaleApps(appsTest, 1 /* instances */)
				checkRegistry(appRegistry, 60*time.Second, 500*time.Millisecond, len(appsTest))

				scaleApps(appsTest, appInstances /* instances */)
				checkRegistry(appRegistry, 60*time.Second, 500*time.Millisecond, len(appsTest)*appInstances)
			}

			close(done)
		}, 30*60 /* <-- overall spec timeout in seconds */)
	})
})

func getToken() string {
	By("getting token")
	cmd := exec.Command("cf", "oauth-token")
	session, err := gexec.Start(cmd, nil, nil)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session.Wait(2 * Timeout_Short)).Should(gexec.Exit(0))
	rawOutput := string(session.Out.Contents())
	return strings.TrimSpace(strings.TrimPrefix(rawOutput, "bearer "))
}

func getGuids(sourceAppName string, dstAppNames []string) (string, []string) {
	dstGuids := []string{}
	sourceGuid := ""
	token := getToken()
	appsClient := rainmaker.NewApplicationsService(rainmaker.Config{Host: "http://" + config.ApiEndpoint})

	appsList, err := appsClient.List(token)
	Expect(err).NotTo(HaveOccurred())

	for {
		for _, app := range appsList.Applications {
			if app.Name == sourceAppName {
				sourceGuid = app.GUID
				continue
			}
			for _, tickAppName := range dstAppNames {
				if app.Name == tickAppName {
					dstGuids = append(dstGuids, app.GUID)
					break
				}
			}
		}
		if appsList.HasNextPage() {
			appsList, err = appsList.Next(token)
			Expect(err).NotTo(HaveOccurred())
		} else {
			break
		}
	}

	Expect(sourceGuid).NotTo(BeEmpty())
	Expect(dstGuids).To(HaveLen(len(dstAppNames)))

	return sourceGuid, dstGuids
}

func doAllPolicies(action string, source string, dstList []string, dstPorts []int) {
	policyClient := policy_client.NewExternal(lagertest.NewTestLogger("test"), &http.Client{}, "http://"+config.ApiEndpoint)
	sourceGuid, dstGuids := getGuids(source, dstList)
	policies := []models.Policy{}
	for _, dstGuid := range dstGuids {
		for _, port := range dstPorts {
			policies = append(policies, models.Policy{
				Source: models.Source{
					ID: sourceGuid,
				},
				Destination: models.Destination{
					ID:       dstGuid,
					Port:     port,
					Protocol: "tcp",
				},
			})
		}
	}
	token := getToken()
	if action == "create" {
		Expect(policyClient.AddPolicies(token, policies)).To(Succeed())
	} else if action == "delete" {
		Expect(policyClient.DeletePolicies(token, policies)).To(Succeed())
	}
}

func runWithTimeout(operation string, timeout time.Duration, work func()) {
	done := make(chan bool)
	go func() {
		fmt.Printf("starting %s\n", operation)
		work()
		done <- true
	}()

	select {
	case <-done:
		fmt.Printf("completed %s\n", operation)
		return
	case <-time.After(timeout):
		Fail("timeout on " + operation)
	}
}

func dumpStats(host, domain string) {
	resp, err := httpGetBytes(fmt.Sprintf("http://%s.%s/stats", host, domain))
	Expect(err).NotTo(HaveOccurred())

	fmt.Printf("STATS: %s\n", string(resp.Body))
	netStatsFile := os.Getenv("NETWORK_STATS_FILE")
	if netStatsFile != "" {
		Expect(ioutil.WriteFile(netStatsFile, resp.Body, 0600)).To(Succeed())
	}
}

type RegistryInstancesResponse struct {
	Instances []struct {
		ServiceName string `json:"service_name"`
		Endpoint    struct {
			Value string `json:"value"`
		} `json:"endpoint"`
	} `json:"instances"`
}

func getInstancesFromA8(registry string) (*RegistryInstancesResponse, error) {
	resp, err := httpGetBytes(fmt.Sprintf("http://%s.%s/api/v1/instances", registry, config.AppsDomain))
	if err != nil {
		return nil, err
	}

	Expect(resp.StatusCode).To(Equal(http.StatusOK))

	var instancesResponse RegistryInstancesResponse
	err = json.Unmarshal(resp.Body, &instancesResponse)
	if err != nil {
		return nil, err
	}
	return &instancesResponse, nil
}

func checkRegistry(registry string, timeout, pollingInterval time.Duration, totalInstances int) {
	registeredApps := func() (int, error) {
		instancesResponse, err := getInstancesFromA8(registry)
		if err != nil {
			return 0, err
		}
		return len(instancesResponse.Instances), nil
	}

	Eventually(registeredApps, timeout, pollingInterval).Should(Equal(totalInstances))
}

func getAppIPs(registry string) []string {
	instancesResponse, err := getInstancesFromA8(registry)
	Expect(err).NotTo(HaveOccurred())

	ips := []string{}
	for _, instance := range instancesResponse.Instances {
		ip, _, err := net.SplitHostPort(instance.Endpoint.Value)
		Expect(err).NotTo(HaveOccurred())
		ips = append(ips, ip)
	}
	return ips
}

func assertConnectionSucceeds(sourceApp string, destApps []string, ports []int, nProxies int) {
	parallelRunner := &testsupport.ParallelRunner{
		NumWorkers: 5 * nProxies,
	}
	parallelRunner.RunOnSliceStrings(destApps, func(appIP string) {
		for _, port := range ports {
			assertSingleConnection(appIP, port, sourceApp, true)
		}
	})
}

func assertConnectionFails(sourceApp string, destApps []string, ports []int, nProxies int) {
	parallelRunner := &testsupport.ParallelRunner{
		NumWorkers: 5 * nProxies,
	}
	parallelRunner.RunOnSliceStrings(destApps, func(appIP string) {
		for _, port := range ports {
			assertSingleConnection(appIP, port, sourceApp, false)
		}
	})
}

func assertSingleConnection(destIP string, port int, sourceAppName string, shouldSucceed bool) {
	if shouldSucceed {
		By(fmt.Sprintf("eventually proxy should reach %s at port %d", destIP, port))
		assertResponseContains(destIP, port, sourceAppName, "application_name")
	} else {
		By(fmt.Sprintf("eventually proxy should NOT reach %s at port %d", destIP, port))
		assertResponseContains(destIP, port, sourceAppName, "request failed")
	}
}

func assertResponseContains(destIP string, port int, sourceAppName string, desiredResponse string) {
	proxyTest := func() (string, error) {
		resp, err := httpGetBytes(fmt.Sprintf("http://%s.%s/proxy/%s:%d", sourceAppName, config.AppsDomain, destIP, port))
		if err != nil {
			return "", err
		}
		return string(resp.Body), nil
	}
	Eventually(proxyTest, 10*time.Second, 500*time.Millisecond).Should(ContainSubstring(desiredResponse))
}

var httpClient = &http.Client{
	Transport: &http.Transport{
		DisableKeepAlives: true,
		Dial: (&net.Dialer{
			Timeout:   4 * time.Second,
			KeepAlive: 0,
		}).Dial,
	},
}

type httpResp struct {
	StatusCode int
	Body       []byte
}

func httpGetBytes(url string) (httpResp, error) {
	resp, err := httpClient.Get(url)
	if err != nil {
		return httpResp{}, err
	}
	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return httpResp{}, err
	}

	return httpResp{resp.StatusCode, respBytes}, nil
}
<commit_msg>Increase parallel checks through proxy app<commit_after>package acceptance_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"lib/models"
	"lib/policy_client"
	"lib/testsupport"
	"net"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"code.cloudfoundry.org/lager/lagertest"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-cf-experimental/rainmaker"
)

const Timeout_Push = 5 * time.Minute
const Timeout_Short = 10 * time.Second

var ports []int

var _ = Describe("connectivity between containers on the overlay network", func() {
	Describe("networking policy", func() {
		var (
			appProxy       string
			appRegistry    string
			appsTest       []string
			appInstances   int
			applications   int
			proxyInstances int
			prefix         string
		)

		BeforeEach(func() {
			appInstances = testConfig.AppInstances
			applications = testConfig.Applications
			proxyInstances = testConfig.ProxyInstances
			if testConfig.Prefix == "" {
				prefix = "scale-"
			} else {
				prefix = testConfig.Prefix
			}

			appProxy = prefix + "proxy"
			appRegistry = prefix + "registry"
			for i := 0; i < applications; i++ {
				appsTest = append(appsTest, fmt.Sprintf(prefix+"tick-%d", i))
			}

			ports = []int{8080}
			for i := 0; i < testConfig.ExtraListenPorts; i++ {
				ports = append(ports, 7000+i)
			}
		})

		AfterEach(func() {
			appReport(appProxy, Timeout_Short)
			appReport(appRegistry, Timeout_Short)
			appsReport(appsTest, Timeout_Short)
		})

		It("allows the user to configure policies", func(done Done) {
			if testConfig.SkipCfPush {
				AuthAsAdmin()
				Expect(cf.Cf("target", "-o", prefix+"org", "-s", prefix+"space").Wait(Timeout_Push)).To(gexec.Exit(0))
			} else {
				cmd := exec.Command("go", "run", "../cf-pusher/cmd/cf-pusher/main.go", "--config", helpers.ConfigPath())
				cmd.Stdout = os.Stdout
				cmd.Stderr = os.Stderr
				fmt.Println("\n-----cf-pusher start ------")
				err := cmd.Run()
				fmt.Println("\n-----cf-pusher done -------")
				Expect(err).NotTo(HaveOccurred())
			}

			By("checking that all test app instances have registered themselves")
			checkRegistry(appRegistry, 60*time.Second, 500*time.Millisecond, len(appsTest)*appInstances)

			appIPs := getAppIPs(appRegistry)

			By("checking that the connection fails")
			runWithTimeout("check connection failures", 5*time.Minute, func() {
				assertConnectionFails(appProxy, appIPs, ports, proxyInstances)
			})

			By("creating policies")
			doAllPolicies("create", appProxy, appsTest, ports)

			// we should wait for minimum (pollInterval * 2)
			By("waiting for policies to be created on cells")
			time.Sleep(10 * time.Second)

			By(fmt.Sprintf("checking that %s can reach %s", appProxy, appsTest))
			runWithTimeout("check connection success", 5*time.Minute, func() {
				assertConnectionSucceeds(appProxy, appIPs, ports, proxyInstances)
			})

			dumpStats(appProxy, config.AppsDomain)

			By("deleting policies")
			doAllPolicies("delete", appProxy, appsTest, ports)

			By(fmt.Sprintf("checking that %s can NOT reach %s", appProxy, appsTest))
			runWithTimeout("check connection failures, again", 5*time.Minute, func() {
				assertConnectionFails(appProxy, appIPs, ports, proxyInstances)
			})

			if !testConfig.SkipCfPush {
				By("checking that the registry updates when apps are scaled")
				scaleApps(appsTest, 1 /* instances */)
				checkRegistry(appRegistry, 60*time.Second, 500*time.Millisecond, len(appsTest))

				scaleApps(appsTest, appInstances /* instances */)
				checkRegistry(appRegistry, 60*time.Second, 500*time.Millisecond, len(appsTest)*appInstances)
			}

			close(done)
		}, 30*60 /* <-- overall spec timeout in seconds */)
	})
})

func getToken() string {
	By("getting token")
	cmd := exec.Command("cf", "oauth-token")
	session, err := gexec.Start(cmd, nil, nil)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session.Wait(2 * Timeout_Short)).Should(gexec.Exit(0))
	rawOutput := string(session.Out.Contents())
	return strings.TrimSpace(strings.TrimPrefix(rawOutput, "bearer "))
}

func getGuids(sourceAppName string, dstAppNames []string) (string, []string) {
	dstGuids := []string{}
	sourceGuid := ""
	token := getToken()
	appsClient := rainmaker.NewApplicationsService(rainmaker.Config{Host: "http://" + config.ApiEndpoint})

	appsList, err := appsClient.List(token)
	Expect(err).NotTo(HaveOccurred())

	for {
		for _, app := range appsList.Applications {
			if app.Name == sourceAppName {
				sourceGuid = app.GUID
				continue
			}
			for _, tickAppName := range dstAppNames {
				if app.Name == tickAppName {
					dstGuids = append(dstGuids, app.GUID)
					break
				}
			}
		}
		if appsList.HasNextPage() {
			appsList, err = appsList.Next(token)
			Expect(err).NotTo(HaveOccurred())
		} else {
			break
		}
	}

	Expect(sourceGuid).NotTo(BeEmpty())
	Expect(dstGuids).To(HaveLen(len(dstAppNames)))

	return sourceGuid, dstGuids
}

func doAllPolicies(action string, source string, dstList []string, dstPorts []int) {
	policyClient := policy_client.NewExternal(lagertest.NewTestLogger("test"), &http.Client{}, "http://"+config.ApiEndpoint)
	sourceGuid, dstGuids := getGuids(source, dstList)
	policies := []models.Policy{}
	for _, dstGuid := range dstGuids {
		for _, port := range dstPorts {
			policies = append(policies, models.Policy{
				Source: models.Source{
					ID: sourceGuid,
				},
				Destination: models.Destination{
					ID:       dstGuid,
					Port:     port,
					Protocol: "tcp",
				},
			})
		}
	}
	token := getToken()
	if action == "create" {
		Expect(policyClient.AddPolicies(token, policies)).To(Succeed())
	} else if action == "delete" {
		Expect(policyClient.DeletePolicies(token, policies)).To(Succeed())
	}
}

func runWithTimeout(operation string, timeout time.Duration, work func()) {
	done := make(chan bool)
	go func() {
		fmt.Printf("starting %s\n", operation)
		work()
		done <- true
	}()

	select {
	case <-done:
		fmt.Printf("completed %s\n", operation)
		return
	case <-time.After(timeout):
		Fail("timeout on " + operation)
	}
}

func dumpStats(host, domain string) {
	resp, err := httpGetBytes(fmt.Sprintf("http://%s.%s/stats", host, domain))
	Expect(err).NotTo(HaveOccurred())

	fmt.Printf("STATS: %s\n", string(resp.Body))
	netStatsFile := os.Getenv("NETWORK_STATS_FILE")
	if netStatsFile != "" {
		Expect(ioutil.WriteFile(netStatsFile, resp.Body, 0600)).To(Succeed())
	}
}

type RegistryInstancesResponse struct {
	Instances []struct {
		ServiceName string `json:"service_name"`
		Endpoint    struct {
			Value string `json:"value"`
		} `json:"endpoint"`
	} `json:"instances"`
}

func getInstancesFromA8(registry string) (*RegistryInstancesResponse, error) {
	resp, err := httpGetBytes(fmt.Sprintf("http://%s.%s/api/v1/instances", registry, config.AppsDomain))
	if err != nil {
		return nil, err
	}

	Expect(resp.StatusCode).To(Equal(http.StatusOK))

	var instancesResponse RegistryInstancesResponse
	err = json.Unmarshal(resp.Body, &instancesResponse)
	if err != nil {
		return nil, err
	}
	return &instancesResponse, nil
}

func checkRegistry(registry string, timeout, pollingInterval time.Duration, totalInstances int) {
	registeredApps := func() (int, error) {
		instancesResponse, err := getInstancesFromA8(registry)
		if err != nil {
			return 0, err
		}
		return len(instancesResponse.Instances), nil
	}

	Eventually(registeredApps, timeout, pollingInterval).Should(Equal(totalInstances))
}

func getAppIPs(registry string) []string {
	instancesResponse, err := getInstancesFromA8(registry)
	Expect(err).NotTo(HaveOccurred())

	ips := []string{}
	for _, instance := range instancesResponse.Instances {
		ip, _, err := net.SplitHostPort(instance.Endpoint.Value)
		Expect(err).NotTo(HaveOccurred())
		ips = append(ips, ip)
	}
	return ips
}

func assertConnectionSucceeds(sourceApp string, destApps []string, ports []int, nProxies int) {
	parallelRunner := &testsupport.ParallelRunner{
		NumWorkers: 50 * nProxies,
	}
	parallelRunner.RunOnSliceStrings(destApps, func(appIP string) {
		for _, port := range ports {
			assertSingleConnection(appIP, port, sourceApp, true)
		}
	})
}

func assertConnectionFails(sourceApp string, destApps []string, ports []int, nProxies int) {
	parallelRunner := &testsupport.ParallelRunner{
		NumWorkers: 50 * nProxies,
	}
	parallelRunner.RunOnSliceStrings(destApps, func(appIP string) {
		for _, port := range ports {
			assertSingleConnection(appIP, port, sourceApp, false)
		}
	})
}

func assertSingleConnection(destIP string, port int, sourceAppName string, shouldSucceed bool) {
	if shouldSucceed {
		By(fmt.Sprintf("eventually proxy should reach %s at port %d", destIP, port))
		assertResponseContains(destIP, port, sourceAppName, "application_name")
	} else {
		By(fmt.Sprintf("eventually proxy should NOT reach %s at port %d", destIP, port))
		assertResponseContains(destIP, port, sourceAppName, "request failed")
	}
}

func assertResponseContains(destIP string, port int, sourceAppName string, desiredResponse string) {
	proxyTest := func() (string, error) {
		resp, err := httpGetBytes(fmt.Sprintf("http://%s.%s/proxy/%s:%d", sourceAppName, config.AppsDomain, destIP, port))
		if err != nil {
			return "", err
		}
		return string(resp.Body), nil
	}
	Eventually(proxyTest, 10*time.Second, 500*time.Millisecond).Should(ContainSubstring(desiredResponse))
}

var httpClient = &http.Client{
	Transport: &http.Transport{
		DisableKeepAlives: true,
		Dial: (&net.Dialer{
			Timeout:   4 * time.Second,
			KeepAlive: 0,
		}).Dial,
	},
}

type httpResp struct {
	StatusCode int
	Body       []byte
}

func httpGetBytes(url string) (httpResp, error) {
	resp, err := httpClient.Get(url)
	if err != nil {
		return httpResp{}, err
	}
	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return httpResp{}, err
	}

	return httpResp{resp.StatusCode, respBytes}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/context"

	pg "github.com/mozilla/tls-observatory/database"
	"github.com/mozilla/tls-observatory/logger"
)

func ScanHandler(w http.ResponseWriter, r *http.Request) {
	var (
		status int
		err    error
	)

	defer func() {
		if nil != err {
			http.Error(w, err.Error(), status)
		}
	}()

	log := logger.GetLogger()
	status = http.StatusInternalServerError

	log.WithFields(logrus.Fields{
		"form values": r.Form,
		"headers":     r.Header,
	}).Debug("Scan endpoint received request")

	val, ok := context.GetOk(r, dbKey)
	if !ok {
		log.Error("Could not find db in request context")
		err = errors.New("Could not access database.")
		return
	}

	db := val.(*pg.DB)

	domain := r.FormValue("target")
	if validateDomain(domain) {

		rescan := false
		if r.FormValue("rescan") == "true" {
			rescan = true
		}

		previd, prevtime, err := db.GetLastScanTimeForTarget(domain)
		if err != nil {
			log.WithFields(logrus.Fields{
				"domain": domain,
				"error":  err.Error(),
			}).Error("Could not get last scan for target")
			err = errors.New("Could not get last scan for target")
			return
		}

		if previd != -1 { // check if previous scan exists
			if time.Now().UTC().Sub(prevtime).Hours() <= 24 {
				if !rescan {
					// no rescan requested so return previous scan in any case
					// this includes the rate limiting with no rescan case
					resp := fmt.Sprintf(`{"scan_id":"%d"}`, previd)
					w.Header().Set("Content-Type", "application/json")
					w.WriteHeader(http.StatusOK)
					fmt.Fprint(w, resp)
					return
				}

				// forced rescan has been requested
				if time.Now().UTC().Sub(prevtime).Minutes() <= 3 { // rate limit scan requests for same target
					if rescan {
						w.WriteHeader(429) // 429 http status code is not exported ( https://codereview.appspot.com/7678043/ )
						fmt.Fprint(w, "")
						return
					}
				}
			}
		}

		//initiating a new scan
		scan, err := db.NewScan(domain, -1) //no replay
		if err != nil {
			log.WithFields(logrus.Fields{
				"domain": domain,
				"error":  err.Error(),
			}).Error("Could not create new scan")
			err = errors.New("Could not create new scan")
			return
		}

		resp := fmt.Sprintf(`{"scan_id":"%d"}`, scan.ID)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, resp)
	} else {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprint(w, "")
	}
}

func ResultHandler(w http.ResponseWriter, r *http.Request) {

	var (
		status int
		err    error
	)

	defer func() {
		if nil != err {
			http.Error(w, err.Error(), status)
		}
	}()

	log := logger.GetLogger()
	status = http.StatusInternalServerError

	log.WithFields(logrus.Fields{
		"form values": r.Form,
		"headers":     r.Header,
	}).Debug("Results endpoint received request")

	val, ok := context.GetOk(r, dbKey)
	if !ok {
		log.Error("Could not find db in request context")
		err = errors.New("Could not access database.")
		return
	}

	db := val.(*pg.DB)

	idStr := r.FormValue("id")

	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		log.WithFields(logrus.Fields{
			"scan_id": idStr,
			"error":   err.Error(),
		}).Error("Could not parse scanid")
		err = errors.New("Could not parse provided scan id")
		status = http.StatusBadRequest
		return
	}

	scan, err := db.GetScanByID(id)
	if err != nil {
		log.WithFields(logrus.Fields{
			"scan_id": id,
			"error":   err.Error(),
		}).Error("Could not get scan from database")
		err = errors.New("Could not access database to get requested scan.")
		return
	}

	if scan.ID == -1 {
		log.WithFields(logrus.Fields{
			"scan_id": id,
		}).Debug("Did not find scan in database")

		err = errors.New("Could not find a scan with the id you provided.")
		status = http.StatusNotFound
		return
	}

	jsScan, err := json.Marshal(scan)
	if err != nil {
		log.WithFields(logrus.Fields{
			"scan_id": id,
			"error":   err.Error(),
		}).Error("Could not Marshal scan")

		err = errors.New("Could not process the requested scan")
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, string(jsScan))
}

func CertificateHandler(w http.ResponseWriter, r *http.Request) {

	var (
		status int
		err    error
	)

	defer func() {
		if nil != err {
			http.Error(w, err.Error(), status)
		}
	}()

	log := logger.GetLogger()
	status = http.StatusInternalServerError

	log.WithFields(logrus.Fields{
		"form values": r.Form.Encode(),
		"headers":     r.Header,
	}).Debug("Certificate Endpoint received request")

	val, ok := context.GetOk(r, dbKey)
	if !ok {
		log.Error("Could not find db in request context")
		err = errors.New("Could not access database.")
		return
	}

	db := val.(*pg.DB)

	idStr := r.FormValue("id")

	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		log.WithFields(logrus.Fields{
			"cert_id": id,
			"error":   err.Error(),
		}).Error("Could not parse certificate id")

		status = http.StatusBadRequest
		err = errors.New("Could not parse provided certificate id")
		return
	}

	cert, err := db.GetCertByID(id)
	if err != nil {
		log.WithFields(logrus.Fields{
			"cert_id": id,
			"error":   err.Error(),
		}).Error("Could not get cert from database")

		err = errors.New("Could not access database to get requested certificate")
		return
	}

	jsScan, err := json.Marshal(cert)
	if err != nil {
		log.WithFields(logrus.Fields{
			"cert_id": id,
			"error":   err.Error(),
		}).Error("Could not Marshal cert")

		err = errors.New("Could not process requested certificate")
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, string(jsScan))
}

func validateDomain(domain string) bool {
	if domain == "" {
		return false
	}
	return true
}
<commit_msg>some go conventions applied...<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/context"

	pg "github.com/mozilla/tls-observatory/database"
	"github.com/mozilla/tls-observatory/logger"
)

// ScanHandler handles the /scans endpoint of the api
// It initiates new scans and returns created scans ids to be used against other endpoints.
func ScanHandler(w http.ResponseWriter, r *http.Request) {
	var (
		status int
		err    error
	)

	defer func() {
		if nil != err {
			http.Error(w, err.Error(), status)
		}
	}()

	log := logger.GetLogger()
	status = http.StatusInternalServerError

	log.WithFields(logrus.Fields{
		"form values": r.Form,
		"headers":     r.Header,
	}).Debug("Scan endpoint received request")

	val, ok := context.GetOk(r, dbKey)
	if !ok {
		log.Error("Could not find db in request context")
		err = errors.New("Could not access database.")
		return
	}

	db := val.(*pg.DB)

	domain := r.FormValue("target")
	if validateDomain(domain) {

		rescan := false
		if r.FormValue("rescan") == "true" {
			rescan = true
		}

		previd, prevtime, err := db.GetLastScanTimeForTarget(domain)
		if err != nil {
			log.WithFields(logrus.Fields{
				"domain": domain,
				"error":  err.Error(),
			}).Error("Could not get last scan for target")
			err = errors.New("Could not get last scan for target")
			return
		}

		if previd != -1 { // check if previous scan exists
			if time.Now().UTC().Sub(prevtime).Hours() <= 24 {
				if !rescan {
					// no rescan requested so return previous scan in any case
					// this includes the rate limiting with no rescan case
					resp := fmt.Sprintf(`{"scan_id":"%d"}`, previd)
					w.Header().Set("Content-Type", "application/json")
					w.WriteHeader(http.StatusOK)
					fmt.Fprint(w, resp)
					return
				}

				// forced rescan has been requested
				if time.Now().UTC().Sub(prevtime).Minutes() <= 3 { // rate limit scan requests for same target
					if rescan {
						w.WriteHeader(429) // 429 http status code is not exported ( https://codereview.appspot.com/7678043/ )
						fmt.Fprint(w, "")
						return
					}
				}
			}
		}

		//initiating a new scan
		scan, err := db.NewScan(domain, -1) //no replay
		if err != nil {
			log.WithFields(logrus.Fields{
				"domain": domain,
				"error":  err.Error(),
			}).Error("Could not create new scan")
			err = errors.New("Could not create new scan")
			return
		}

		resp := fmt.Sprintf(`{"scan_id":"%d"}`, scan.ID)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, resp)
	} else {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprint(w, "")
	}
}

// ResultHandler handles the results endpoint of the api.
// It has a scan id as input and returns its results ( if available )
func ResultHandler(w http.ResponseWriter, r *http.Request) {

	var (
		status int
		err    error
	)

	defer func() {
		if nil != err {
			http.Error(w, err.Error(), status)
		}
	}()

	log := logger.GetLogger()
	status = http.StatusInternalServerError

	log.WithFields(logrus.Fields{
		"form values": r.Form,
		"headers":     r.Header,
	}).Debug("Results endpoint received request")

	val, ok := context.GetOk(r, dbKey)
	if !ok {
		log.Error("Could not find db in request context")
		err = errors.New("Could not access database.")
		return
	}

	db := val.(*pg.DB)

	idStr := r.FormValue("id")

	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		log.WithFields(logrus.Fields{
			"scan_id": idStr,
			"error":   err.Error(),
		}).Error("Could not parse scanid")
		err = errors.New("Could not parse provided scan id")
		status = http.StatusBadRequest
		return
	}

	scan, err := db.GetScanByID(id)
	if err != nil {
		log.WithFields(logrus.Fields{
			"scan_id": id,
			"error":   err.Error(),
		}).Error("Could not get scan from database")
		err = errors.New("Could not access database to get requested scan.")
		return
	}

	if scan.ID == -1 {
		log.WithFields(logrus.Fields{
			"scan_id": id,
		}).Debug("Did not find scan in database")

		err = errors.New("Could not find a scan with the id you provided.")
		status = http.StatusNotFound
		return
	}

	jsScan, err := json.Marshal(scan)
	if err != nil {
		log.WithFields(logrus.Fields{
			"scan_id": id,
			"error":   err.Error(),
		}).Error("Could not Marshal scan")

		err = errors.New("Could not process the requested scan")
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, string(jsScan))
}

// CertificateHandler handles the /certificate endpoint of the api.
// It queries the database for the provided cert ids and returns results in JSON.
func CertificateHandler(w http.ResponseWriter, r *http.Request) {

	var (
		status int
		err    error
	)

	defer func() {
		if nil != err {
			http.Error(w, err.Error(), status)
		}
	}()

	log := logger.GetLogger()
	status = http.StatusInternalServerError

	log.WithFields(logrus.Fields{
		"form values": r.Form.Encode(),
		"headers":     r.Header,
	}).Debug("Certificate Endpoint received request")

	val, ok := context.GetOk(r, dbKey)
	if !ok {
		log.Error("Could not find db in request context")
		err = errors.New("Could not access database.")
		return
	}

	db := val.(*pg.DB)

	idStr := r.FormValue("id")

	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		log.WithFields(logrus.Fields{
			"cert_id": id,
			"error":   err.Error(),
		}).Error("Could not parse certificate id")

		status = http.StatusBadRequest
		err = errors.New("Could not parse provided certificate id")
		return
	}

	cert, err := db.GetCertByID(id)
	if err != nil {
		log.WithFields(logrus.Fields{
			"cert_id": id,
			"error":   err.Error(),
		}).Error("Could not get cert from database")

		err = errors.New("Could not access database to get requested certificate")
		return
	}

	jsScan, err := json.Marshal(cert)
	if err != nil {
		log.WithFields(logrus.Fields{
			"cert_id": id,
			"error":   err.Error(),
		}).Error("Could not Marshal cert")

		err = errors.New("Could not process requested certificate")
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, string(jsScan))
}

func validateDomain(domain string) bool {
	if domain == "" {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package send

import (
	"bytes"
	"sync"

	"github.com/mongodb/grip/level"
	"github.com/mongodb/grip/message"
)

var newLine = []byte{'\n'}

// WriterSender wraps another sender and also provides an io.Writer.
// (and because Sender is an io.Closer) the type also implements
// io.WriteCloser.
type WriterSender struct {
	Sender
	buffer   []byte
	priority level.Priority
	mu       sync.Mutex
}

// NewWriterSender wraps another sender and also provides an io.Writer.
// (and because Sender is an io.Closer) the type also implements
// io.WriteCloser.
//
// While WriteSender itself implements Sender, it also provides a
// Writer method, which allows you to use this Sender to capture
// file-like write operations.
//
// Data sent via the Write method is buffered internally until its
// passed a byte slice that ends with the new line character. If the
// string form of the bytes passed to the write method (including all
// buffered messages) is only whitespace, then it is not sent.
//
// If there are any bytes in the buffer when the Close method is
// called, this sender flushes the buffer before closing the underlying sender.
func NewWriterSender(s Sender) *WriterSender {
	return &WriterSender{Sender: s, priority: s.Level().Default}
}

// MakeWriterSender returns an sender interface that also implements
// io.Writer. Specify a priority used as the level for messages sent.
func MakeWriterSender(s Sender, p level.Priority) *WriterSender {
	return &WriterSender{Sender: s, priority: p}
}

// Write captures a sequence of bytes to the send interface. It never errors.
func (s *WriterSender) Write(p []byte) (int, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// capture the number of bytes in the input so we can return
	// the proper amount
	n := len(p)

	// if the logged message does *not* end in a new line, we
	// should buffer it until we find one that does.
	if !bytes.HasSuffix(p, newLine) {
		s.buffer = append(s.buffer, p...)
		return n, nil
	}
	// we're ready to write the log message

	// if we had something in the buffer, we should prepend it to
	// the current message, and clear the buffer.
	if len(s.buffer) >= 1 {
		p = append(s.buffer, p...)
		s.buffer = []byte{}
	}

	// Now send each log message:
	s.doSend(s.priority, p)
	return n, nil
}

func (s *WriterSender) doSend(l level.Priority, buf []byte) {
	for _, val := range bytes.Split(buf, newLine) {
		if len(bytes.Trim(val, " \t")) != 0 {
			s.Send(message.NewBytesMessage(l, val))
		}
	}
}

// Close writes any buffered messages to the underlying Sender before
// closing that Sender.
func (s *WriterSender) Close() error {
	s.mu.Lock()
	defer s.mu.Unlock()

	if len(s.buffer) >= 1 {
		s.doSend(s.Level().Default, s.buffer)
		s.buffer = []byte{}
	}

	return s.Sender.Close()
}
<commit_msg>WriterSender should not close underlying Sender<commit_after>package send

import (
	"bytes"
	"sync"

	"github.com/mongodb/grip/level"
	"github.com/mongodb/grip/message"
)

var newLine = []byte{'\n'}

// WriterSender wraps another sender and also provides an io.Writer.
// (and because Sender is an io.Closer) the type also implements
// io.WriteCloser.
type WriterSender struct {
	Sender
	buffer   []byte
	priority level.Priority
	mu       sync.Mutex
}

// NewWriterSender wraps another sender and also provides an io.Writer.
// (and because Sender is an io.Closer) the type also implements
// io.WriteCloser.
//
// While WriteSender itself implements Sender, it also provides a
// Writer method, which allows you to use this Sender to capture
// file-like write operations.
//
// Data sent via the Write method is buffered internally until its
// passed a byte slice that ends with the new line character. If the
// string form of the bytes passed to the write method (including all
// buffered messages) is only whitespace, then it is not sent.
//
// If there are any bytes in the buffer when the Close method is
// called, this sender flushes the buffer before closing the underlying sender.
func NewWriterSender(s Sender) *WriterSender {
	return &WriterSender{Sender: s, priority: s.Level().Default}
}

// MakeWriterSender returns an sender interface that also implements
// io.Writer. Specify a priority used as the level for messages sent.
func MakeWriterSender(s Sender, p level.Priority) *WriterSender {
	return &WriterSender{Sender: s, priority: p}
}

// Write captures a sequence of bytes to the send interface. It never errors.
func (s *WriterSender) Write(p []byte) (int, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// capture the number of bytes in the input so we can return
	// the proper amount
	n := len(p)

	// if the logged message does *not* end in a new line, we
	// should buffer it until we find one that does.
	if !bytes.HasSuffix(p, newLine) {
		s.buffer = append(s.buffer, p...)
		return n, nil
	}
	// we're ready to write the log message

	// if we had something in the buffer, we should prepend it to
	// the current message, and clear the buffer.
	if len(s.buffer) >= 1 {
		p = append(s.buffer, p...)
		s.buffer = []byte{}
	}

	// Now send each log message:
	s.doSend(s.priority, p)
	return n, nil
}

func (s *WriterSender) doSend(l level.Priority, buf []byte) {
	for _, val := range bytes.Split(buf, newLine) {
		if len(bytes.Trim(val, " \t")) != 0 {
			s.Send(message.NewBytesMessage(l, val))
		}
	}
}

// Close writes any buffered messages to the underlying Sender before
// closing that Sender.
func (s *WriterSender) Close() error {
	s.mu.Lock()
	defer s.mu.Unlock()

	if len(s.buffer) >= 1 {
		s.doSend(s.Level().Default, s.buffer)
		s.buffer = []byte{}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import "fmt"

var arwServer ARWServer

func main() {
	arwServer.Initialize()

	arwServer.AddExtensionHandler("FindRoom", FindRoomHandler)
	arwServer.ProcessEvents()
}

func FindRoomHandler(arwServer *ARWServer, user User, obj ARWObject) {
	fmt.Println("===>> Find Room Request")
	roomTag := obj.GetString("roomTag")

	findedRoom, err := arwServer.roomManager.SearchRoomWithTag(roomTag)

	if err != "" {
		// Create Room
		var roomSettings RoomSettings
		roomSettings.name = roomTag
		roomSettings.tag = roomTag
		roomSettings.cappacity = 4
		roomSettings.maxRoomVariableCount = 10
		roomSettings.InitializeMethod = RoomInitializeMethod

		newRoom := arwServer.roomManager.CreateRoom(roomSettings, arwServer)
		newRoom.AddUserToRoom(arwServer, user)
		return
	}

	r := &findedRoom
	r.AddUserToRoom(arwServer, user)
}

func RoomInitializeMethod(arwServer *ARWServer, room *Room) {
	fmt.Println("Room Initialize Success " + room.name)
	// room.AddExtensionHandler("IamReady", IamReadyHandler)
	room.AddExtensionHandler("VerticalUpdate", VerticalUpdateHandler)
	room.AddExtensionHandler("HorizontalUpdate", HorizontalUpdateHandler)
}

func VerticalUpdateHandler(arwServer *ARWServer, user User, obj ARWObject) {
	obj.PutInt("userId", user.id)

	arwServer.roomManager.allRooms[0].SendRequestAllUserWithoutMe(*arwServer, obj, user)
}

func HorizontalUpdateHandler(arwServer *ARWServer, user User, obj ARWObject) {
	obj.PutInt("userId", user.id)

	arwServer.roomManager.allRooms[0].SendRequestAllUserWithoutMe(*arwServer, obj, user)
}
<commit_msg>Example Server code<commit_after>package main

import "fmt"

var arwServer ARWServer

func main() {
	arwServer.Initialize()

	arwServer.AddExtensionHandler("FindRoom", FindRoomHandler)
	arwServer.ProcessEvents()
}

func FindRoomHandler(arwServer *ARWServer, user *User, obj ARWObject) {
	fmt.Println("===>> Find Room Request")
	roomTag, _ := obj.GetString("roomTag")

	findedRoom, err := arwServer.roomManager.SearchRoomWithTag(roomTag)

	if err != nil {
		// Create Room
		var roomSettings RoomSettings
		roomSettings.name = roomTag
		roomSettings.tag = roomTag
		roomSettings.cappacity = 4
		roomSettings.maxRoomVariableCount = 10
		roomSettings.InitializeMethod = RoomInitializeMethod

		newRoom := arwServer.roomManager.CreateRoom(roomSettings, arwServer)
		newRoom.AddUserToRoom(arwServer, user)
		return
	}

	findedRoom.AddUserToRoom(arwServer, user)
}

func RoomInitializeMethod(arwServer *ARWServer, room *Room) {
	fmt.Println("Room Initialize Success " + room.name)
	// room.AddExtensionHandler("IamReady", IamReadyHandler)
	room.AddExtensionHandler("VerticalUpdate", VerticalUpdateHandler)
	room.AddExtensionHandler("HorizontalUpdate", HorizontalUpdateHandler)
}

func VerticalUpdateHandler(arwServer *ARWServer, user *User, obj ARWObject) {
	obj.PutInt("userId", user.id)

	arwServer.roomManager.allRooms[0].SendRequestAllUserWithoutMe(*arwServer, obj, *user)
}

func HorizontalUpdateHandler(arwServer *ARWServer, user *User, obj ARWObject) {
	obj.PutInt("userId", user.id)

	arwServer.roomManager.allRooms[0].SendRequestAllUserWithoutMe(*arwServer, obj, *user)
}
<|endoftext|>


<commit_before>// Copyright 2012-2017 Apcera Inc. All rights reserved.

package server

import (
	"crypto/tls"
	"fmt"
	"strings"

	"golang.org/x/crypto/bcrypt"
)

// Authentication is an interface for implementing authentication
type Authentication interface {
	// Check if a client is authorized to connect
	Check(c ClientAuthentication) bool
}

// ClientAuthentication is an interface for client authentication
type ClientAuthentication interface {
	// Get options associated with a client
	GetOpts() *clientOpts
	// If TLS is enabled, TLS ConnectionState, nil otherwise
	GetTLSConnectionState() *tls.ConnectionState
	// Optionally map a user after auth.
	RegisterUser(*User)
}

// User is for multiple accounts/users.
type User struct {
	Username    string       `json:"user"`
	Password    string       `json:"password"`
	Permissions *Permissions `json:"permissions"`
}

// clone performs a deep copy of the User struct, returning a new clone with
// all values copied.
func (u *User) clone() *User {
	if u == nil {
		return nil
	}
	clone := &User{}
	*clone = *u
	clone.Permissions = u.Permissions.clone()
	return clone
}

// Permissions are the allowed subjects on a per
// publish or subscribe basis.
type Permissions struct {
	Publish   []string `json:"publish"`
	Subscribe []string `json:"subscribe"`
}

// clone performs a deep copy of the Permissions struct, returning a new clone
// with all values copied.
func (p *Permissions) clone() *Permissions {
	if p == nil {
		return nil
	}
	clone := &Permissions{}
	if p.Publish != nil {
		clone.Publish = make([]string, len(p.Publish))
		copy(clone.Publish, p.Publish)
	}
	if p.Subscribe != nil {
		clone.Subscribe = make([]string, len(p.Subscribe))
		copy(clone.Subscribe, p.Subscribe)
	}
	return clone
}

// configureAuthorization will do any setup needed for authorization.
// Lock is assumed held.
func (s *Server) configureAuthorization() {
	if s.opts == nil {
		return
	}

	// Snapshot server options.
	opts := s.getOpts()

	// Check for multiple users first
	// This just checks and sets up the user map if we have multiple users.
	if opts.Users != nil {
		s.users = make(map[string]*User)
		for _, u := range opts.Users {
			s.users[u.Username] = u
		}
		s.info.AuthRequired = true
	} else if opts.Username != "" || opts.Authorization != "" {
		s.info.AuthRequired = true
	} else {
		s.users = nil
		s.info.AuthRequired = false
	}
}

// checkAuthorization will check authorization based on client type and
// return boolean indicating if client is authorized.
func (s *Server) checkAuthorization(c *client) bool {
	switch c.typ {
	case CLIENT:
		return s.isClientAuthorized(c)
	case ROUTER:
		return s.isRouterAuthorized(c)
	default:
		return false
	}
}

// isClientAuthorized will check the client against the proper authorization method and data.
// This could be token or username/password based.
func (s *Server) isClientAuthorized(c *client) bool {
	// Snapshot server options.
	opts := s.getOpts()

	// Check custom auth first, then multiple users, then token, then single user/pass.
	if s.opts.CustomClientAuthentication != nil {
		return s.opts.CustomClientAuthentication.Check(c)
	} else if s.users != nil {
		user, ok := s.users[c.opts.Username]
		if !ok {
			return false
		}
		ok = comparePasswords(user.Password, c.opts.Password)
		// If we are authorized, register the user which will properly setup any permissions
		// for pub/sub authorizations.
		if ok {
			c.RegisterUser(user)
		}
		return ok

	} else if opts.Authorization != "" {
		return comparePasswords(opts.Authorization, c.opts.Authorization)

	} else if opts.Username != "" {
		if opts.Username != c.opts.Username {
			return false
		}
		return comparePasswords(opts.Password, c.opts.Password)
	}

	return true
}

// checkRouterAuth checks optional router authorization which can be nil or username/password.
func (s *Server) isRouterAuthorized(c *client) bool {
	// Snapshot server options.
	opts := s.getOpts()

	if s.opts.CustomRouterAuthentication != nil {
		return s.opts.CustomRouterAuthentication.Check(c)
	}

	if opts.Cluster.Username == "" {
		return true
	}

	if opts.Cluster.Username != c.opts.Username {
		return false
	}
	return comparePasswords(opts.Cluster.Password, c.opts.Password)
}

// removeUnauthorizedSubs removes any subscriptions the client has that are no
// longer authorized, e.g. due to a config reload.
func (s *Server) removeUnauthorizedSubs(c *client) {
	c.mu.Lock()
	if c.perms == nil {
		c.mu.Unlock()
		return
	}

	subs := make(map[string]*subscription, len(c.subs))
	for sid, sub := range c.subs {
		subs[sid] = sub
	}
	c.mu.Unlock()

	for sid, sub := range subs {
		if !c.canSubscribe(sub.subject) {
			_ = s.sl.Remove(sub)
			c.mu.Lock()
			delete(c.subs, sid)
			c.mu.Unlock()
			c.sendErr(fmt.Sprintf("Permissions Violation for Subscription to %q (sid %s)",
				sub.subject, sub.sid))
			s.Noticef("Removed sub %q for user %q - not authorized",
				string(sub.subject), c.opts.Username)
		}
	}
}

// Support for bcrypt stored passwords and tokens.
const bcryptPrefix = "$2a$"

// isBcrypt checks whether the given password or token is bcrypted.
func isBcrypt(password string) bool {
	return strings.HasPrefix(password, bcryptPrefix)
}

func comparePasswords(serverPassword, clientPassword string) bool {
	// Check to see if the server password is a bcrypt hash
	if isBcrypt(serverPassword) {
		if err := bcrypt.CompareHashAndPassword([]byte(serverPassword), []byte(clientPassword)); err != nil {
			return false
		}
	} else if serverPassword != clientPassword {
		return false
	}
	return true
}
<commit_msg>Set info.AuthRequired when CustomClientAuthentication is defined<commit_after>// Copyright 2012-2017 Apcera Inc. All rights reserved.

package server

import (
	"crypto/tls"
	"fmt"
	"strings"

	"golang.org/x/crypto/bcrypt"
)

// Authentication is an interface for implementing authentication
type Authentication interface {
	// Check if a client is authorized to connect
	Check(c ClientAuthentication) bool
}

// ClientAuthentication is an interface for client authentication
type ClientAuthentication interface {
	// Get options associated with a client
	GetOpts() *clientOpts
	// If TLS is enabled, TLS ConnectionState, nil otherwise
	GetTLSConnectionState() *tls.ConnectionState
	// Optionally map a user after auth.
	RegisterUser(*User)
}

// User is for multiple accounts/users.
type User struct {
	Username    string       `json:"user"`
	Password    string       `json:"password"`
	Permissions *Permissions `json:"permissions"`
}

// clone performs a deep copy of the User struct, returning a new clone with
// all values copied.
func (u *User) clone() *User {
	if u == nil {
		return nil
	}
	clone := &User{}
	*clone = *u
	clone.Permissions = u.Permissions.clone()
	return clone
}

// Permissions are the allowed subjects on a per
// publish or subscribe basis.
type Permissions struct {
	Publish   []string `json:"publish"`
	Subscribe []string `json:"subscribe"`
}

// clone performs a deep copy of the Permissions struct, returning a new clone
// with all values copied.
func (p *Permissions) clone() *Permissions {
	if p == nil {
		return nil
	}
	clone := &Permissions{}
	if p.Publish != nil {
		clone.Publish = make([]string, len(p.Publish))
		copy(clone.Publish, p.Publish)
	}
	if p.Subscribe != nil {
		clone.Subscribe = make([]string, len(p.Subscribe))
		copy(clone.Subscribe, p.Subscribe)
	}
	return clone
}

// configureAuthorization will do any setup needed for authorization.
// Lock is assumed held.
func (s *Server) configureAuthorization() {
	if s.opts == nil {
		return
	}

	// Snapshot server options.
	opts := s.getOpts()

	// Check for multiple users first
	// This just checks and sets up the user map if we have multiple users.
	if opts.CustomClientAuthentication != nil {
		s.info.AuthRequired = true
	} else if opts.Users != nil {
		s.users = make(map[string]*User)
		for _, u := range opts.Users {
			s.users[u.Username] = u
		}
		s.info.AuthRequired = true
	} else if opts.Username != "" || opts.Authorization != "" {
		s.info.AuthRequired = true
	} else {
		s.users = nil
		s.info.AuthRequired = false
	}
}

// checkAuthorization will check authorization based on client type and
// return boolean indicating if client is authorized.
func (s *Server) checkAuthorization(c *client) bool {
	switch c.typ {
	case CLIENT:
		return s.isClientAuthorized(c)
	case ROUTER:
		return s.isRouterAuthorized(c)
	default:
		return false
	}
}

// isClientAuthorized will check the client against the proper authorization method and data.
// This could be token or username/password based.
func (s *Server) isClientAuthorized(c *client) bool {
	// Snapshot server options.
	opts := s.getOpts()

	// Check custom auth first, then multiple users, then token, then single user/pass.
	if s.opts.CustomClientAuthentication != nil {
		return s.opts.CustomClientAuthentication.Check(c)
	} else if s.users != nil {
		user, ok := s.users[c.opts.Username]
		if !ok {
			return false
		}
		ok = comparePasswords(user.Password, c.opts.Password)
		// If we are authorized, register the user which will properly setup any permissions
		// for pub/sub authorizations.
		if ok {
			c.RegisterUser(user)
		}
		return ok

	} else if opts.Authorization != "" {
		return comparePasswords(opts.Authorization, c.opts.Authorization)

	} else if opts.Username != "" {
		if opts.Username != c.opts.Username {
			return false
		}
		return comparePasswords(opts.Password, c.opts.Password)
	}

	return true
}

// checkRouterAuth checks optional router authorization which can be nil or username/password.
func (s *Server) isRouterAuthorized(c *client) bool {
	// Snapshot server options.
	opts := s.getOpts()

	if s.opts.CustomRouterAuthentication != nil {
		return s.opts.CustomRouterAuthentication.Check(c)
	}

	if opts.Cluster.Username == "" {
		return true
	}

	if opts.Cluster.Username != c.opts.Username {
		return false
	}
	return comparePasswords(opts.Cluster.Password, c.opts.Password)
}

// removeUnauthorizedSubs removes any subscriptions the client has that are no
// longer authorized, e.g. due to a config reload.
func (s *Server) removeUnauthorizedSubs(c *client) {
	c.mu.Lock()
	if c.perms == nil {
		c.mu.Unlock()
		return
	}

	subs := make(map[string]*subscription, len(c.subs))
	for sid, sub := range c.subs {
		subs[sid] = sub
	}
	c.mu.Unlock()

	for sid, sub := range subs {
		if !c.canSubscribe(sub.subject) {
			_ = s.sl.Remove(sub)
			c.mu.Lock()
			delete(c.subs, sid)
			c.mu.Unlock()
			c.sendErr(fmt.Sprintf("Permissions Violation for Subscription to %q (sid %s)",
				sub.subject, sub.sid))
			s.Noticef("Removed sub %q for user %q - not authorized",
				string(sub.subject), c.opts.Username)
		}
	}
}

// Support for bcrypt stored passwords and tokens.
const bcryptPrefix = "$2a$"

// isBcrypt checks whether the given password or token is bcrypted.
func isBcrypt(password string) bool {
	return strings.HasPrefix(password, bcryptPrefix)
}

func comparePasswords(serverPassword, clientPassword string) bool {
	// Check to see if the server password is a bcrypt hash
	if isBcrypt(serverPassword) {
		if err := bcrypt.CompareHashAndPassword([]byte(serverPassword), []byte(clientPassword)); err != nil {
			return false
		}
	} else if serverPassword != clientPassword {
		return false
	}
	return true
}
<|endoftext|>