aboutsummaryrefslogblamecommitdiffstats
path: root/clients/ssh/git_upload_pack_test.go
blob: 8626b50c0964ee074c0b44ca76c59db43f4067be (plain) (tree)


























                                                                   
                                             































                                                                 



                                                         
                                             






                                                               
                                                   



                                                                                                           
                                                   



                                                                                  
                                                         










                                                                                         
                                             




                                                                                       



                                                         
                                             






                                                                                     



                                                         
                                             





                                                               
                                                    



                                                         



                                                         
                                             






                                                               



                                                         
                                             














                                                               
                                             




                                               



                                                         
                                             








                                                                                          



                                                         
                                             








                                                                  
                                               






                                                                         



                                                         
                                             











                                                                         
package ssh

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"

	"golang.org/x/crypto/ssh/agent"

	. "gopkg.in/check.v1"
	"gopkg.in/src-d/go-git.v2/clients/common"
	"gopkg.in/src-d/go-git.v2/core"
)

type SuiteRemote struct{}

var _ = Suite(&SuiteRemote{})

const (
	fixRepo             = "git@github.com:tyba/git-fixture.git"
	fixRepoBadVcs       = "www.example.com"
	fixRepoNonGit       = "https://code.google.com/p/go"
	fixGitRepoNonGithub = "https://bitbucket.org/user/repo.git"
)

func (s *SuiteRemote) TestConnect(c *C) {
	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.Connect(fixRepo), Equals, ErrAuthRequired)
}

// We will use a running ssh agent for testing
// ssh authentication.
type sshAgentConn struct {
	pipe net.Conn
	auth *PublicKeysCallback
}

// Opens a pipe with the ssh agent and uses the pipe
// as the implementer of the public key callback function.
func newSSHAgentConn() (*sshAgentConn, error) {
	pipe, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
	if err != nil {
		return nil, err
	}
	return &sshAgentConn{
		pipe: pipe,
		auth: &PublicKeysCallback{
			User:     "git",
			Callback: agent.NewClient(pipe).Signers,
		},
	}, nil
}

// Closes the pipe with the ssh agent
func (c *sshAgentConn) close() error {
	return c.pipe.Close()
}

func (s *SuiteRemote) TestConnectWithPublicKeysCallback(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	defer func() { c.Assert(r.Disconnect(), IsNil) }()
	c.Assert(r.connected, Equals, true)
	c.Assert(r.auth, Equals, agent.auth)
}

func (s *SuiteRemote) TestConnectBadVcs(c *C) {
	r := NewGitUploadPackService(fixRepoBadVcs)
	c.Assert(r.ConnectWithAuth(fixRepoBadVcs, nil), ErrorMatches, fmt.Sprintf(".*%s.*", fixRepoBadVcs))
}

func (s *SuiteRemote) TestConnectNonGit(c *C) {
	r := NewGitUploadPackService(fixRepoNonGit)
	c.Assert(r.ConnectWithAuth(fixRepoNonGit, nil), Equals, ErrUnsupportedVCS)
}

func (s *SuiteRemote) TestConnectNonGithub(c *C) {
	r := NewGitUploadPackService(fixGitRepoNonGithub)
	c.Assert(r.ConnectWithAuth(fixGitRepoNonGithub, nil), Equals, ErrUnsupportedRepo)
}

// A mock implementation of client.common.AuthMethod
// to test non ssh auth method detection.
type mockAuth struct{}

func (*mockAuth) Name() string   { return "" }
func (*mockAuth) String() string { return "" }

func (s *SuiteRemote) TestConnectWithAuthWrongType(c *C) {
	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, &mockAuth{}), Equals, ErrInvalidAuthMethod)
	c.Assert(r.connected, Equals, false)
}

func (s *SuiteRemote) TestAlreadyConnected(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	defer func() { c.Assert(r.Disconnect(), IsNil) }()
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), Equals, ErrAlreadyConnected)
	c.Assert(r.connected, Equals, true)
}

func (s *SuiteRemote) TestDisconnect(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	c.Assert(r.Disconnect(), IsNil)
	c.Assert(r.connected, Equals, false)
}

func (s *SuiteRemote) TestDisconnectedWhenNonConnected(c *C) {
	r := NewGitUploadPackService("Dear Twinkle")
	c.Assert(r.Disconnect(), Equals, ErrNotConnected)
}

func (s *SuiteRemote) TestAlreadyDisconnected(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	c.Assert(r.Disconnect(), IsNil)
	c.Assert(r.Disconnect(), Equals, ErrNotConnected)
	c.Assert(r.connected, Equals, false)
}

func (s *SuiteRemote) TestServeralConnections(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	c.Assert(r.Disconnect(), IsNil)

	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	c.Assert(r.connected, Equals, true)
	c.Assert(r.Disconnect(), IsNil)
	c.Assert(r.connected, Equals, false)

	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	c.Assert(r.connected, Equals, true)
	c.Assert(r.Disconnect(), IsNil)
	c.Assert(r.connected, Equals, false)
}

func (s *SuiteRemote) TestInfoNotConnected(c *C) {
	r := NewGitUploadPackService(fixRepo)
	_, err := r.Info()
	c.Assert(err, Equals, ErrNotConnected)
}

func (s *SuiteRemote) TestDefaultBranch(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	defer func() { c.Assert(r.Disconnect(), IsNil) }()

	info, err := r.Info()
	c.Assert(err, IsNil)
	c.Assert(info.Capabilities.SymbolicReference("HEAD"), Equals, "refs/heads/master")
}

func (s *SuiteRemote) TestCapabilities(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	defer func() { c.Assert(r.Disconnect(), IsNil) }()

	info, err := r.Info()
	c.Assert(err, IsNil)
	c.Assert(info.Capabilities.Get("agent").Values, HasLen, 1)
}

func (s *SuiteRemote) TestFetchNotConnected(c *C) {
	r := NewGitUploadPackService("foo bar")
	pr := &common.GitUploadPackRequest{}
	pr.Want(core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
	_, err := r.Fetch(pr)
	c.Assert(err, Equals, ErrNotConnected)
}

func (s *SuiteRemote) TestFetch(c *C) {
	agent, err := newSSHAgentConn()
	c.Assert(err, IsNil)
	defer func() { c.Assert(agent.close(), IsNil) }()

	r := NewGitUploadPackService(fixRepo)
	c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
	defer func() { c.Assert(r.Disconnect(), IsNil) }()

	pr := &common.GitUploadPackRequest{}
	pr.Want(core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
	reader, err := r.Fetch(pr)
	c.Assert(err, IsNil)

	b, err := ioutil.ReadAll(reader)
	c.Assert(err, IsNil)
	c.Assert(b, HasLen, 85374)
}