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