aboutsummaryrefslogblamecommitdiffstats
path: root/clients/ssh/git_upload_pack_test.go
blob: 3a0a983abdf1e12575dea8da1e03f3771dde6274 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13

             










                                       

                                                 













                                                                   
                                      






























                                                                 





                                                  
                                                               



                                                         
                                      






                                                               
                                      



                                                                                                           
                                      



                                                                                  
                                      










                                                                                         
                                      




                                                                                       



                                                         
                                      






                                                                                     



                                                         
                                      





                                                               
                                      



                                                         



                                                         
                                      






                                                               



                                                         
                                      














                                                               
                                      




                                               



                                                         
                                      








                                                                                          



                                                         
                                      








                                                                  
                                      






                                                                         



                                                         
                                      











                                                                         
// +build ssh

package ssh

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

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

	. "gopkg.in/check.v1"
	"gopkg.in/src-d/go-git.v4/clients/common"
	"gopkg.in/src-d/go-git.v4/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()
	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) SetUpSuite(c *C) {
	if os.Getenv("SSH_AUTH_SOCK") == "" {
		c.Skip("SSH_AUTH_SOCK is not set")
	}
}

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

	r := NewGitUploadPackService()
	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()
	c.Assert(r.ConnectWithAuth(fixRepoBadVcs, nil), ErrorMatches, fmt.Sprintf(".*%s.*", fixRepoBadVcs))
}

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

func (s *SuiteRemote) TestConnectNonGithub(c *C) {
	r := NewGitUploadPackService()
	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()
	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()
	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()
	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()
	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()
	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()
	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()
	_, 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()
	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()
	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()
	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()
	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)
}