chore: add server tests

Ayman Bagabas created

Change summary

.gitignore                |   1 
server/middleware.go      |   1 
server/middleware_test.go |  28 +++++++++
server/server.go          |   5 +
server/server_test.go     | 115 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 150 insertions(+)

Detailed changes

.gitignore 🔗

@@ -2,3 +2,4 @@ cmd/soft/soft
 .ssh
 .repos
 dist
+testdata

server/middleware.go 🔗

@@ -47,6 +47,7 @@ func softServeMiddleware(ac *appCfg.Config) wish.Middleware {
 					for _, rp := range ac.Source.AllRepos() {
 						if rp.Name() == repo {
 							repoExists = true
+							break
 						}
 					}
 					if !repoExists {

server/middleware_test.go 🔗

@@ -0,0 +1,28 @@
+package server
+
+import (
+	"testing"
+
+	"github.com/charmbracelet/soft-serve/internal/config"
+	"github.com/charmbracelet/wish/testsession"
+	"github.com/gliderlabs/ssh"
+	"github.com/matryer/is"
+)
+
+var ()
+
+func TestMiddleware(t *testing.T) {
+	is := is.New(t)
+	appCfg, err := config.NewConfig(cfg)
+	is.NoErr(err)
+	_ = testsession.New(t, &ssh.Server{
+		Handler: softServeMiddleware(appCfg)(func(s ssh.Session) {
+			t.Run("TestCatConfig", func(t *testing.T) {
+				_, err := s.Write([]byte("config/config.json"))
+				if err == nil {
+					t.Errorf("Expected error, got nil")
+				}
+			})
+		}),
+	}, nil)
+}

server/server.go 🔗

@@ -73,3 +73,8 @@ func (srv *Server) Start() error {
 func (srv *Server) Shutdown(ctx context.Context) error {
 	return srv.SSHServer.Shutdown(ctx)
 }
+
+// Close closes the SSH server.
+func (srv *Server) Close() error {
+	return srv.SSHServer.Close()
+}

server/server_test.go 🔗

@@ -0,0 +1,115 @@
+package server
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/charmbracelet/keygen"
+	"github.com/charmbracelet/soft-serve/config"
+	"github.com/gliderlabs/ssh"
+	"github.com/go-git/go-git/v5"
+	gconfig "github.com/go-git/go-git/v5/config"
+	"github.com/go-git/go-git/v5/plumbing/object"
+	gssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
+	"github.com/matryer/is"
+	cssh "golang.org/x/crypto/ssh"
+)
+
+var (
+	testdata = "testdata"
+	cfg      = &config.Config{
+		BindAddr: "",
+		Host:     "localhost",
+		Port:     22222,
+		RepoPath: fmt.Sprintf("%s/repos", testdata),
+		KeyPath:  fmt.Sprintf("%s/key", testdata),
+	}
+	pkPath = ""
+)
+
+func TestServer(t *testing.T) {
+	t.Cleanup(func() {
+		os.RemoveAll(testdata)
+	})
+	is := is.New(t)
+	_, pkPath = createKeyPair(t)
+	s := setupServer(t)
+	err := s.Reload()
+	is.NoErr(err)
+	t.Run("TestPushRepo", testPushRepo)
+	t.Run("TestCloneRepo", testCloneRepo)
+}
+
+func testPushRepo(t *testing.T) {
+	is := is.New(t)
+	rp := t.TempDir()
+	r, err := git.PlainInit(rp, false)
+	is.NoErr(err)
+	wt, err := r.Worktree()
+	is.NoErr(err)
+	_, err = wt.Filesystem.Create("testfile")
+	is.NoErr(err)
+	_, err = wt.Add("testfile")
+	is.NoErr(err)
+	author := &object.Signature{
+		Name:  "test",
+		Email: "",
+	}
+	_, err = wt.Commit("test commit", &git.CommitOptions{
+		All:       true,
+		Author:    author,
+		Committer: author,
+	})
+	is.NoErr(err)
+	_, err = r.CreateRemote(&gconfig.RemoteConfig{
+		Name: "origin",
+		URLs: []string{fmt.Sprintf("ssh://%s:%d/%s", cfg.Host, cfg.Port, "testrepo")},
+	})
+	auth, err := gssh.NewPublicKeysFromFile("git", pkPath, "")
+	is.NoErr(err)
+	auth.HostKeyCallbackHelper = gssh.HostKeyCallbackHelper{
+		HostKeyCallback: cssh.InsecureIgnoreHostKey(),
+	}
+	err = r.Push(&git.PushOptions{
+		RemoteName: "origin",
+		Auth:       auth,
+	})
+	is.NoErr(err)
+}
+
+func testCloneRepo(t *testing.T) {
+	is := is.New(t)
+	auth, err := gssh.NewPublicKeysFromFile("git", pkPath, "")
+	is.NoErr(err)
+	auth.HostKeyCallbackHelper = gssh.HostKeyCallbackHelper{
+		HostKeyCallback: cssh.InsecureIgnoreHostKey(),
+	}
+	dst := t.TempDir()
+	_, err = git.PlainClone(dst, false, &git.CloneOptions{
+		URL:  fmt.Sprintf("ssh://%s:%d/config", cfg.Host, cfg.Port),
+		Auth: auth,
+	})
+	is.NoErr(err)
+}
+
+func setupServer(t *testing.T) *Server {
+	s := NewServer(cfg)
+	go func() {
+		s.Start()
+	}()
+	defer s.Close()
+	return s
+}
+
+func createKeyPair(t *testing.T) (ssh.PublicKey, string) {
+	is := is.New(t)
+	t.Helper()
+	keyDir := t.TempDir()
+	kp, err := keygen.NewWithWrite(keyDir, "id", nil, keygen.Ed25519)
+	is.NoErr(err)
+	pubkey, _, _, _, err := ssh.ParseAuthorizedKey(kp.PublicKey)
+	is.NoErr(err)
+	return pubkey, filepath.Join(keyDir, "id_ed25519")
+}