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}