From 5cd607b89aad06f3f56373d7716343abd7728ed0 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Wed, 14 Jan 2015 19:30:43 +0000 Subject: [PATCH] Unix socket-based HTTP API test functionality. As a consequence this also required making some hardcoded values into more generic functionality, which is generally a good thing. I verified that each test function that I modified still passed.: This code is copyright 2014 Akamai Technologies, Inc. --- api/api_test.go | 112 +++++++++++++++++++++++++++++++-------------- api/status_test.go | 47 ++++++++++++++++++- 2 files changed, 123 insertions(+), 36 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index 4b697ba58..beb448cf1 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -2,6 +2,7 @@ package api import ( crand "crypto/rand" + "encoding/json" "fmt" "io/ioutil" "net/http" @@ -13,27 +14,48 @@ import ( "github.com/hashicorp/consul/testutil" ) -var consulConfig = `{ - "ports": { - "dns": 19000, - "http": 18800, - "rpc": 18600, - "serf_lan": 18200, - "serf_wan": 18400, - "server": 18000 - }, - "data_dir": "%s", - "bootstrap": true, - "log_level": "debug", - "server": true -}` - type testServer struct { pid int dataDir string configFile string } +type TestPortConfig struct { + DNS int `json:"dns,omitempty"` + HTTP int `json:"http,omitempty"` + RPC int `json:"rpc,omitempty"` + SerfLan int `json:"serf_lan,omitempty"` + SerfWan int `json:"serf_wan,omitempty"` + Server int `json:"server,omitempty"` +} + +type TestAddressConfig struct { + HTTP string `json:"http,omitempty"` +} + +type TestServerConfig struct { + Bootstrap bool `json:"bootstrap,omitempty"` + Server bool `json:"server,omitempty"` + DataDir string `json:"data_dir,omitempty"` + LogLevel string `json:"log_level,omitempty"` + Addresses *TestAddressConfig `json:"addresses,omitempty"` + Ports TestPortConfig `json:"ports,omitempty"` +} + +var consulConfig = &TestServerConfig{ + Bootstrap: true, + Server: true, + LogLevel: "debug", + Ports: TestPortConfig{ + DNS: 19000, + HTTP: 18800, + RPC: 18600, + SerfLan: 18200, + SerfWan: 18400, + Server: 18000, + }, +} + func (s *testServer) stop() { defer os.RemoveAll(s.dataDir) defer os.RemoveAll(s.configFile) @@ -45,6 +67,10 @@ func (s *testServer) stop() { } func newTestServer(t *testing.T) *testServer { + return newTestServerWithConfig(t, func(c *TestServerConfig) {}) +} + +func newTestServerWithConfig(t *testing.T, cb func(c *TestServerConfig)) *testServer { if path, err := exec.LookPath("consul"); err != nil || path == "" { t.Log("consul not found on $PATH, skipping") t.SkipNow() @@ -66,8 +92,17 @@ func newTestServer(t *testing.T) *testServer { if err != nil { t.Fatalf("err: %s", err) } - configContent := fmt.Sprintf(consulConfig, dataDir) - if _, err := configFile.WriteString(configContent); err != nil { + + consulConfig.DataDir = dataDir + + cb(consulConfig) + + configContent, err := json.Marshal(consulConfig) + if err != nil { + t.Fatalf("err: %s", err) + } + + if _, err := configFile.Write(configContent); err != nil { t.Fatalf("err: %s", err) } configFile.Close() @@ -80,10 +115,32 @@ func newTestServer(t *testing.T) *testServer { t.Fatalf("err: %s", err) } + return &testServer{ + pid: cmd.Process.Pid, + dataDir: dataDir, + configFile: configFile.Name(), + } +} + +func makeClient(t *testing.T) (*Client, *testServer) { + return makeClientWithConfig(t, func(c *Config) { + c.Address = "127.0.0.1:18800" + }, func(c *TestServerConfig) {}) +} + +func makeClientWithConfig(t *testing.T, clientConfig func(c *Config), serverConfig func(c *TestServerConfig)) (*Client, *testServer) { + server := newTestServerWithConfig(t, serverConfig) + conf := DefaultConfig() + clientConfig(conf) + client, err := NewClient(conf) + if err != nil { + t.Fatalf("err: %v", err) + } + // Allow the server some time to start, and verify we have a leader. - client := new(http.Client) testutil.WaitForResult(func() (bool, error) { - resp, err := client.Get("http://127.0.0.1:18800/v1/catalog/nodes") + req := client.newRequest("GET", "/v1/catalog/nodes") + _, resp, err := client.doRequest(req) if err != nil { return false, err } @@ -102,21 +159,6 @@ func newTestServer(t *testing.T) *testServer { t.Fatalf("err: %s", err) }) - return &testServer{ - pid: cmd.Process.Pid, - dataDir: dataDir, - configFile: configFile.Name(), - } -} - -func makeClient(t *testing.T) (*Client, *testServer) { - server := newTestServer(t) - conf := DefaultConfig() - conf.Address = "127.0.0.1:18800" - client, err := NewClient(conf) - if err != nil { - t.Fatalf("err: %v", err) - } return client, server } @@ -205,7 +247,7 @@ func TestRequestToHTTP(t *testing.T) { if req.Method != "DELETE" { t.Fatalf("bad: %v", req) } - if req.URL.String() != "http://127.0.0.1:18800/v1/kv/foo?dc=foo" { + if req.URL.RequestURI() != "/v1/kv/foo?dc=foo" { t.Fatalf("bad: %v", req) } } diff --git a/api/status_test.go b/api/status_test.go index 096b13da0..4bdd3b2df 100644 --- a/api/status_test.go +++ b/api/status_test.go @@ -1,10 +1,13 @@ package api import ( + "io/ioutil" + "os/user" + "runtime" "testing" ) -func TestStatusLeader(t *testing.T) { +func TestStatusLeaderTCP(t *testing.T) { c, s := makeClient(t) defer s.stop() @@ -19,6 +22,48 @@ func TestStatusLeader(t *testing.T) { } } +func TestStatusLeaderUnix(t *testing.T) { + if runtime.GOOS == "windows" { + t.SkipNow() + } + + tempdir, err := ioutil.TempDir("", "consul-test-") + if err != nil { + t.Fatal("Could not create a working directory") + } + + socket := "unix://" + tempdir + "/unix-http-test.sock" + + clientConfig := func(c *Config) { + c.Address = socket + } + + serverConfig := func(c *TestServerConfig) { + user, err := user.Current() + if err != nil { + t.Fatal("Could not get current user") + } + + if c.Addresses == nil { + c.Addresses = &TestAddressConfig{} + } + c.Addresses.HTTP = socket + ";" + user.Uid + ";" + user.Gid + ";640" + } + + c, s := makeClientWithConfig(t, clientConfig, serverConfig) + defer s.stop() + + status := c.Status() + + leader, err := status.Leader() + if err != nil { + t.Fatalf("err: %v", err) + } + if leader == "" { + t.Fatalf("Expected leader") + } +} + func TestStatusPeers(t *testing.T) { c, s := makeClient(t) defer s.stop()