1package server
2
3import (
4 "errors"
5 "fmt"
6 "log"
7 "os"
8 "testing"
9 "time"
10
11 "github.com/charmbracelet/soft-serve/server/backend/sqlite"
12 "github.com/charmbracelet/soft-serve/server/config"
13 "github.com/charmbracelet/ssh"
14 bm "github.com/charmbracelet/wish/bubbletea"
15 "github.com/charmbracelet/wish/testsession"
16 "github.com/matryer/is"
17 "github.com/muesli/termenv"
18 gossh "golang.org/x/crypto/ssh"
19)
20
21func TestSession(t *testing.T) {
22 is := is.New(t)
23 t.Run("authorized repo access", func(t *testing.T) {
24 t.Log("setting up")
25 s, close := setup(t)
26 s.Stderr = os.Stderr
27 t.Log("requesting pty")
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 t.Log("waiting for session to exit")
37 _, err = s.Output("test")
38 var ee *gossh.ExitMissingError
39 is.True(errors.As(err, &ee))
40 t.Log("session exited")
41 _ = close()
42 })
43}
44
45func setup(tb testing.TB) (*gossh.Session, func() error) {
46 tb.Helper()
47 is := is.New(tb)
48 dp := tb.TempDir()
49 is.NoErr(os.Setenv("SOFT_SERVE_DATA_PATH", dp))
50 is.NoErr(os.Setenv("SOFT_SERVE_GIT_LISTEN_ADDR", ":9418"))
51 is.NoErr(os.Setenv("SOFT_SERVE_SSH_LISTEN_ADDR", fmt.Sprintf(":%d", randomPort())))
52 tb.Cleanup(func() {
53 is.NoErr(os.Unsetenv("SOFT_SERVE_DATA_PATH"))
54 is.NoErr(os.Unsetenv("SOFT_SERVE_GIT_LISTEN_ADDR"))
55 is.NoErr(os.Unsetenv("SOFT_SERVE_SSH_LISTEN_ADDR"))
56 is.NoErr(os.RemoveAll(dp))
57 })
58 cfg := config.DefaultConfig()
59 fb, err := sqlite.NewSqliteBackend(cfg)
60 if err != nil {
61 log.Fatal(err)
62 }
63 cfg = cfg.WithBackend(fb)
64 return testsession.New(tb, &ssh.Server{
65 Handler: bm.MiddlewareWithProgramHandler(SessionHandler(cfg), termenv.ANSI256)(func(s ssh.Session) {
66 _, _, active := s.Pty()
67 if !active {
68 os.Exit(1)
69 }
70 s.Exit(0)
71 }),
72 }, nil), fb.Close
73}