1package server
 2
 3import (
 4	"errors"
 5	"fmt"
 6	"log"
 7	"os"
 8	"path/filepath"
 9	"testing"
10	"time"
11
12	"github.com/charmbracelet/soft-serve/server/backend/file"
13	"github.com/charmbracelet/soft-serve/server/config"
14	"github.com/charmbracelet/ssh"
15	bm "github.com/charmbracelet/wish/bubbletea"
16	"github.com/charmbracelet/wish/testsession"
17	"github.com/matryer/is"
18	"github.com/muesli/termenv"
19	gossh "golang.org/x/crypto/ssh"
20)
21
22func TestSession(t *testing.T) {
23	is := is.New(t)
24	t.Run("authorized repo access", func(t *testing.T) {
25		s := setup(t)
26		s.Stderr = os.Stderr
27		defer s.Close()
28		err := s.RequestPty("xterm", 80, 40, nil)
29		is.NoErr(err)
30		go func() {
31			time.Sleep(1 * time.Second)
32			s.Signal(gossh.SIGTERM)
33			// FIXME: exit with code 0 instead of forcibly closing the session
34			s.Close()
35		}()
36		err = s.Run("test")
37		var ee *gossh.ExitMissingError
38		is.True(errors.As(err, &ee))
39	})
40}
41
42func setup(tb testing.TB) *gossh.Session {
43	tb.Helper()
44	is := is.New(tb)
45	dp := tb.TempDir()
46	is.NoErr(os.Setenv("SOFT_SERVE_DATA_PATH", dp))
47	is.NoErr(os.Setenv("SOFT_SERVE_GIT_LISTEN_ADDR", ":9418"))
48	is.NoErr(os.Setenv("SOFT_SERVE_SSH_LISTEN_ADDR", fmt.Sprintf(":%d", randomPort())))
49	tb.Cleanup(func() {
50		is.NoErr(os.Unsetenv("SOFT_SERVE_DATA_PATH"))
51		is.NoErr(os.Unsetenv("SOFT_SERVE_GIT_LISTEN_ADDR"))
52		is.NoErr(os.Unsetenv("SOFT_SERVE_SSH_LISTEN_ADDR"))
53		is.NoErr(os.RemoveAll(dp))
54	})
55	fb, err := file.NewFileBackend(filepath.Join(dp, "repos"))
56	if err != nil {
57		log.Fatal(err)
58	}
59	cfg := config.DefaultConfig().WithBackend(fb)
60	return testsession.New(tb, &ssh.Server{
61		Handler: bm.MiddlewareWithProgramHandler(SessionHandler(cfg), termenv.ANSI256)(func(s ssh.Session) {
62			_, _, active := s.Pty()
63			tb.Logf("PTY active %v", active)
64			tb.Log(s.Command())
65			s.Exit(0)
66		}),
67	}, nil)
68}