session_test.go

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