session_test.go

 1package ssh
 2
 3import (
 4	"context"
 5	"errors"
 6	"fmt"
 7	"os"
 8	"testing"
 9	"time"
10
11	"github.com/charmbracelet/log"
12	"github.com/charmbracelet/soft-serve/server/backend"
13	"github.com/charmbracelet/soft-serve/server/config"
14	"github.com/charmbracelet/soft-serve/server/db"
15	"github.com/charmbracelet/soft-serve/server/db/migrate"
16	"github.com/charmbracelet/soft-serve/server/test"
17	"github.com/charmbracelet/ssh"
18	bm "github.com/charmbracelet/wish/bubbletea"
19	"github.com/charmbracelet/wish/testsession"
20	"github.com/matryer/is"
21	"github.com/muesli/termenv"
22	gossh "golang.org/x/crypto/ssh"
23	_ "modernc.org/sqlite" // sqlite driver
24)
25
26func TestSession(t *testing.T) {
27	is := is.New(t)
28	t.Run("authorized repo access", func(t *testing.T) {
29		t.Log("setting up")
30		s, close := setup(t)
31		s.Stderr = os.Stderr
32		t.Log("requesting pty")
33		err := s.RequestPty("xterm", 80, 40, nil)
34		is.NoErr(err)
35		go func() {
36			time.Sleep(1 * time.Second)
37			// s.Signal(gossh.SIGTERM)
38			s.Close() // nolint: errcheck
39		}()
40		t.Log("waiting for session to exit")
41		_, err = s.Output("test")
42		var ee *gossh.ExitMissingError
43		is.True(errors.As(err, &ee))
44		t.Log("session exited")
45		is.NoErr(close())
46	})
47}
48
49func setup(tb testing.TB) (*gossh.Session, func() error) {
50	tb.Helper()
51	is := is.New(tb)
52	dp := tb.TempDir()
53	is.NoErr(os.Setenv("SOFT_SERVE_DATA_PATH", dp))
54	is.NoErr(os.Setenv("SOFT_SERVE_GIT_LISTEN_ADDR", ":9418"))
55	is.NoErr(os.Setenv("SOFT_SERVE_SSH_LISTEN_ADDR", fmt.Sprintf(":%d", test.RandomPort())))
56	tb.Cleanup(func() {
57		is.NoErr(os.Unsetenv("SOFT_SERVE_DATA_PATH"))
58		is.NoErr(os.Unsetenv("SOFT_SERVE_GIT_LISTEN_ADDR"))
59		is.NoErr(os.Unsetenv("SOFT_SERVE_SSH_LISTEN_ADDR"))
60		is.NoErr(os.RemoveAll(dp))
61	})
62	ctx := context.TODO()
63	cfg := config.DefaultConfig()
64	if err := cfg.Validate(); err != nil {
65		log.Fatal(err)
66	}
67	ctx = config.WithContext(ctx, cfg)
68	db, err := db.Open(ctx, cfg.DB.Driver, cfg.DB.DataSource)
69	if err != nil {
70		tb.Fatal(err)
71	}
72	if err := migrate.Migrate(ctx, db); err != nil {
73		tb.Fatal(err)
74	}
75	be := backend.New(ctx, cfg, db)
76	ctx = backend.WithContext(ctx, be)
77	return testsession.New(tb, &ssh.Server{
78		Handler: ContextMiddleware(cfg, be, log.Default())(bm.MiddlewareWithProgramHandler(SessionHandler, termenv.ANSI256)(func(s ssh.Session) {
79			_, _, active := s.Pty()
80			if !active {
81				os.Exit(1)
82			}
83			s.Exit(0)
84		})),
85	}, nil), db.Close
86}