Skip to content
Snippets Groups Projects
Commit 411cab50 authored by Nick Thomas's avatar Nick Thomas Committed by Nick Thomas
Browse files

Add a simple test for MultiStringFlag

parent e5d0aa9a
No related branches found
No related tags found
1 merge request!6Allow -listen-http, -listen-https and -listen-proxy to be given more than once
Loading
Loading
@@ -2,127 +2,42 @@ package main
 
import (
"flag"
"fmt"
"github.com/stretchr/testify/assert"
"net"
"net/http"
"os"
"os/exec"
"testing"
"time"
)
 
// TODO: Use TCP port 0 everywhere to avoid conflicts. The binary could output
// the actual port (and type of listener) for us to read in place of the
// hardcoded values below.
type listenSpec struct {
Type string
Host string
Port string
}
func (l listenSpec) URL(suffix string) string {
scheme := "http"
if l.Type == "https" {
scheme = "https"
}
return fmt.Sprintf("%s://%s/%s", scheme, l.JoinHostPort(), suffix)
}
// Returns only once the TCP server is open
func (l listenSpec) WaitUntilListening() {
for {
conn, _ := net.Dial("tcp", l.JoinHostPort())
if conn != nil {
conn.Close()
break
}
}
}
func (l listenSpec) JoinHostPort() string {
return net.JoinHostPort(l.Host, l.Port)
}
var shouldRun = flag.Bool("run-acceptance-tests", false, "Run the acceptance tests?")
var pagesBinary = flag.String("gitlab-pages-binary", "./gitlab-pages", "Path to the gitlab-pages binary")
 
var listenHTTP = []listenSpec{
{"http", "127.0.0.1", "3700"},
{"http", "::1", "3700"},
}
// TODO: listenHTTPS will require TLS configuration
var listenHTTPS = []listenSpec{}
var listenProxy = []listenSpec{
{"proxy", "127.0.0.1", "3702"},
// TODO: Use TCP port 0 everywhere to avoid conflicts. The binary could output
// the actual port (and type of listener) for us to read in place of the
// hardcoded values below.
var listeners = []ListenSpec{
{"http", "127.0.0.1", "37000"},
{"http", "::1", "37000"},
{"https", "127.0.0.1", "37001"},
{"https", "::1", "37001"},
{"proxy", "127.0.0.1", "37002"},
{"proxy", "::1", "37002"},
}
 
var listeners = append(listenHTTP, append(listenHTTPS, listenProxy...)...)
// TODO: start one pages process for all tests?
func runPages(t *testing.T) *exec.Cmd {
if !*shouldRun {
t.Log("Acceptance tests disabled")
t.SkipNow()
}
if _, err := os.Stat(*pagesBinary); err != nil {
t.Logf("Can't find Gitlab Pages binary (%s): %s", *pagesBinary, err)
t.FailNow()
func skipUnlessEnabled(t *testing.T) {
if *shouldRun {
return
}
 
var args []string
for _, spec := range listeners {
args = append(args, "-listen-"+spec.Type, spec.JoinHostPort())
}
cmd := exec.Command(*pagesBinary, args...)
t.Logf("Running %s %v", *pagesBinary, args)
cmd.Start()
// Wait for all TCP servers to be open. Even with this, gitlab-pages
// will sometimes return 404 if a HTTP request comes in before it has
// updated its set of domains. This usually takes < 1ms, hence the sleep
// for now. Without it, intermittent failures occur.
//
// TODO: replace this with explicit status from the pages binary
// TODO: fix the first-request race
for _, spec := range listeners {
spec.WaitUntilListening()
}
time.Sleep(50 * time.Millisecond)
return cmd
}
func stopPages(cmd *exec.Cmd) {
cmd.Process.Kill()
cmd.Process.Wait()
}
func getPage(t *testing.T, spec listenSpec, host, urlsuffix string) (*http.Response, error) {
url := spec.URL(urlsuffix)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Host = host
t.Logf("curl -H'Host: %s' %s", host, url)
return http.DefaultClient.Do(req)
t.Log("Acceptance tests disabled")
t.SkipNow()
}
 
func TestUnknownHostReturnsNotFound(t *testing.T) {
cmd := runPages(t)
defer stopPages(cmd)
skipUnlessEnabled(t)
teardown := RunPagesProcess(t, *pagesBinary, listeners)
defer teardown()
 
for _, spec := range listeners {
rsp, err := getPage(t, spec, "invalid.invalid", "")
rsp, err := GetPageFromListener(t, spec, "invalid.invalid", "")
 
if assert.NoError(t, err) {
rsp.Body.Close()
Loading
Loading
@@ -132,11 +47,12 @@ func TestUnknownHostReturnsNotFound(t *testing.T) {
}
 
func TestKnownHostReturns200(t *testing.T) {
cmd := runPages(t)
defer stopPages(cmd)
skipUnlessEnabled(t)
teardown := RunPagesProcess(t, *pagesBinary, listeners)
defer teardown()
 
for _, spec := range listeners {
rsp, err := getPage(t, spec, "group.gitlab-example.com", "project/")
rsp, err := GetPageFromListener(t, spec, "group.gitlab-example.com", "project/")
 
if assert.NoError(t, err) {
rsp.Body.Close()
Loading
Loading
Loading
Loading
@@ -139,38 +139,9 @@ func TestDomainCertificate(t *testing.T) {
Group: "group",
Project: "project2",
Config: &domainConfig{
Domain: "test.domain.com",
Certificate: `-----BEGIN CERTIFICATE-----
MIICWDCCAcGgAwIBAgIJAMyzCfoGEwVNMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTYwMjExMTcxNzM2WhcNMjYwMjA4MTcxNzM2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQC2ZSzGIlv2zRsELkmEA1JcvIdsFv80b0NbBftewDAQRuyPlhGNifFx6v7+3O1F
5+f+So43N0QbdrHu11K+ZuXNc6hUy0ofG/eRqXniGZEn8paUdQ98sWsbWelBDNeg
WX4FQomynjyxbG+3IuJR5UHoLWhrJ9+pbPrT915eObbaTQIDAQABo1AwTjAdBgNV
HQ4EFgQUGAhDu+gfckg4IkHRCQWBn4ltKV4wHwYDVR0jBBgwFoAUGAhDu+gfckg4
IkHRCQWBn4ltKV4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAaGx5U
JRW5HC9dXADLf9OnmJRqWi3VNXEXWFk5XgHKc1z7KIBWMsdj+1gzm5ltRO7hkHw9
bx6jQKZBRiUxyqTFw9Ywrk1fYFAxk8hxuqVYcGdonImJarHZTdVMBRWut9+EZBVm
77eYbz2zASNpy++QIg85YgQum9uqREClHRBsxQ==
-----END CERTIFICATE-----`,
Key: `-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALZlLMYiW/bNGwQu
SYQDUly8h2wW/zRvQ1sF+17AMBBG7I+WEY2J8XHq/v7c7UXn5/5Kjjc3RBt2se7X
Ur5m5c1zqFTLSh8b95GpeeIZkSfylpR1D3yxaxtZ6UEM16BZfgVCibKePLFsb7ci
4lHlQegtaGsn36ls+tP3Xl45ttpNAgMBAAECgYAAqZFmDs3isY/9jeV6c0CjUZP0
UokOubC27eihyXTjOj61rsfVicC0tzPB3S+HZ3YyODcYAD1hFCdFRMbqJhmDiewK
5GfATdNQeNARCfJdjYn57NKaXm7rc4C3so1YfxTL6k9QGJgTcybXiClQPDrhkZt3
YLIeeJbY3OppLqjzgQJBAN5AzwyUqX5eQIUncQKcFY0PIjfFTku62brT7hq+TlqY
1B6n3GUtIX+tyYg1qusy4KUUSzMslXJubHsxKanGqZ0CQQDSFwzK7KEYoZol5OMX
mRsavc3iXmmEkkNRdNb1R4UqrlasPeeIeO1CfoD2RPcQhZCwFtR8xS8u6X9ncfC4
qyxxAkAhpQvy6ppR7/Cyd4sLCxfUF8NlT/APVMTbHHQCBmcUHeiWj3C0vEVC78r/
XKh4HGaXdt//ajNhdEflykZ1VgadAkB6Zh934mEA3rXWOgHsb7EQ5WAb8HF9YVGD
FZVfFaoJ8cRhWTeZlQp14Qn1cLyYjZh8XvCxOJiCtlsZw5JBpMihAkBA6ltWb+aZ
EBjC8ZRwZE+cAzmxaYPSs2J7JhS7X7H7Ax7ShhvHI4br3nqf00H4LkvtcHkn5d9G
MwE1w2r4Deww
-----END PRIVATE KEY-----`,
Domain: "test.domain.com",
Certificate: CertificateFixture,
Key: KeyFixture,
},
}
 
Loading
Loading
package main
 
import (
"crypto/tls"
"fmt"
"github.com/stretchr/testify/assert"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"os/exec"
"testing"
"time"
)
 
var chdirSet = false
Loading
Loading
@@ -19,3 +28,166 @@ func setUpTests() {
chdirSet = true
}
}
// The HTTPS certificate isn't signed by anyone. This http client is set up
// so it can talk to servers using it.
var InsecureHTTPSClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
var CertificateFixture = `-----BEGIN CERTIFICATE-----
MIICWDCCAcGgAwIBAgIJAMyzCfoGEwVNMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTYwMjExMTcxNzM2WhcNMjYwMjA4MTcxNzM2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQC2ZSzGIlv2zRsELkmEA1JcvIdsFv80b0NbBftewDAQRuyPlhGNifFx6v7+3O1F
5+f+So43N0QbdrHu11K+ZuXNc6hUy0ofG/eRqXniGZEn8paUdQ98sWsbWelBDNeg
WX4FQomynjyxbG+3IuJR5UHoLWhrJ9+pbPrT915eObbaTQIDAQABo1AwTjAdBgNV
HQ4EFgQUGAhDu+gfckg4IkHRCQWBn4ltKV4wHwYDVR0jBBgwFoAUGAhDu+gfckg4
IkHRCQWBn4ltKV4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAaGx5U
JRW5HC9dXADLf9OnmJRqWi3VNXEXWFk5XgHKc1z7KIBWMsdj+1gzm5ltRO7hkHw9
bx6jQKZBRiUxyqTFw9Ywrk1fYFAxk8hxuqVYcGdonImJarHZTdVMBRWut9+EZBVm
77eYbz2zASNpy++QIg85YgQum9uqREClHRBsxQ==
-----END CERTIFICATE-----`
var KeyFixture = `-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALZlLMYiW/bNGwQu
SYQDUly8h2wW/zRvQ1sF+17AMBBG7I+WEY2J8XHq/v7c7UXn5/5Kjjc3RBt2se7X
Ur5m5c1zqFTLSh8b95GpeeIZkSfylpR1D3yxaxtZ6UEM16BZfgVCibKePLFsb7ci
4lHlQegtaGsn36ls+tP3Xl45ttpNAgMBAAECgYAAqZFmDs3isY/9jeV6c0CjUZP0
UokOubC27eihyXTjOj61rsfVicC0tzPB3S+HZ3YyODcYAD1hFCdFRMbqJhmDiewK
5GfATdNQeNARCfJdjYn57NKaXm7rc4C3so1YfxTL6k9QGJgTcybXiClQPDrhkZt3
YLIeeJbY3OppLqjzgQJBAN5AzwyUqX5eQIUncQKcFY0PIjfFTku62brT7hq+TlqY
1B6n3GUtIX+tyYg1qusy4KUUSzMslXJubHsxKanGqZ0CQQDSFwzK7KEYoZol5OMX
mRsavc3iXmmEkkNRdNb1R4UqrlasPeeIeO1CfoD2RPcQhZCwFtR8xS8u6X9ncfC4
qyxxAkAhpQvy6ppR7/Cyd4sLCxfUF8NlT/APVMTbHHQCBmcUHeiWj3C0vEVC78r/
XKh4HGaXdt//ajNhdEflykZ1VgadAkB6Zh934mEA3rXWOgHsb7EQ5WAb8HF9YVGD
FZVfFaoJ8cRhWTeZlQp14Qn1cLyYjZh8XvCxOJiCtlsZw5JBpMihAkBA6ltWb+aZ
EBjC8ZRwZE+cAzmxaYPSs2J7JhS7X7H7Ax7ShhvHI4br3nqf00H4LkvtcHkn5d9G
MwE1w2r4Deww
-----END PRIVATE KEY-----`
func CreateHTTPSFixtureFiles(t *testing.T) (key string, cert string) {
keyfile, err := ioutil.TempFile("", "https-fixture")
assert.NoError(t, err)
key = keyfile.Name()
keyfile.Close()
certfile, err := ioutil.TempFile("", "https-fixture")
assert.NoError(t, err)
cert = certfile.Name()
certfile.Close()
assert.NoError(t, ioutil.WriteFile(key, []byte(KeyFixture), 0644))
assert.NoError(t, ioutil.WriteFile(cert, []byte(CertificateFixture), 0644))
return keyfile.Name(), certfile.Name()
}
// ListenSpec is used to point at a gitlab-pages http server, preserving the
// type of port it is (http, https, proxy)
type ListenSpec struct {
Type string
Host string
Port string
}
func (l ListenSpec) URL(suffix string) string {
scheme := "http"
if l.Type == "https" {
scheme = "https"
}
return fmt.Sprintf("%s://%s/%s", scheme, l.JoinHostPort(), suffix)
}
// Returns only once this spec points at a working TCP server
func (l ListenSpec) WaitUntilListening() {
for {
conn, _ := net.Dial("tcp", l.JoinHostPort())
if conn != nil {
conn.Close()
break
}
}
}
func (l ListenSpec) JoinHostPort() string {
return net.JoinHostPort(l.Host, l.Port)
}
// RunPagesProcess will start a gitlab-pages process with the specified listeners
// and return a function you can call to shut it down again. Use
// GetPageFromProcess to do a HTTP GET against a listener.
//
// If run as root via sudo, the gitlab-pages process will drop privileges
func RunPagesProcess(t *testing.T, pagesPath string, listeners []ListenSpec) (teardown func()) {
var tempfiles []string
var args []string
var hasHTTPS bool
_, err := os.Stat(pagesPath)
assert.NoError(t, err)
for _, spec := range listeners {
args = append(args, "-listen-"+spec.Type, spec.JoinHostPort())
if spec.Type == "https" {
hasHTTPS = true
}
}
if hasHTTPS {
key, cert := CreateHTTPSFixtureFiles(t)
tempfiles = []string{key, cert}
args = append(args, "-root-key", key, "-root-cert", cert)
}
if os.Geteuid() == 0 && os.Getenv("SUDO_UID") != "" && os.Getenv("SUDO_GID") != "" {
t.Log("Pages process will drop privileges")
args = append(args, "-daemon-uid", os.Getenv("SUDO_UID"), "-daemon-gid", os.Getenv("SUDO_GID"))
}
cmd := exec.Command(pagesPath, args...)
t.Logf("Running %s %v", pagesPath, args)
cmd.Start()
// Wait for all TCP servers to be open. Even with this, gitlab-pages
// will sometimes return 404 if a HTTP request comes in before it has
// updated its set of domains. This usually takes < 1ms, hence the sleep
// for now. Without it, intermittent failures occur.
//
// TODO: replace this with explicit status from the pages binary
// TODO: fix the first-request race
for _, spec := range listeners {
spec.WaitUntilListening()
}
time.Sleep(50 * time.Millisecond)
return func() {
cmd.Process.Kill()
cmd.Process.Wait()
for _, tempfile := range tempfiles {
os.Remove(tempfile)
}
}
}
// Does an insecure HTTP GET against the listener specified, setting a fake
// Host: and constructing the URL from the listener and the URL suffix.
func GetPageFromListener(t *testing.T, spec ListenSpec, host, urlsuffix string) (*http.Response, error) {
url := spec.URL(urlsuffix)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Host = host
t.Logf("curl -H'Host: %s' %s", host, url)
return InsecureHTTPSClient.Do(req)
}
package main
import (
"flag"
"github.com/stretchr/testify/assert"
"testing"
)
func TestMultiStringFlagAppendsOnSet(t *testing.T) {
var concrete MultiStringFlag
var iface flag.Value
iface = &concrete
assert.NoError(t, iface.Set("foo"))
assert.NoError(t, iface.Set("bar"))
assert.Equal(t, MultiStringFlag{"foo", "bar"}, concrete)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment