1package ssh23import (4 "context"5 "errors"6 "fmt"7 "os"8 "testing"9 "time"1011 "charm.land/log/v2"12 bm "charm.land/wish/v2/bubbletea"13 "charm.land/wish/v2/testsession"14 "github.com/charmbracelet/soft-serve/pkg/backend"15 "github.com/charmbracelet/soft-serve/pkg/config"16 "github.com/charmbracelet/soft-serve/pkg/db"17 "github.com/charmbracelet/soft-serve/pkg/db/migrate"18 "github.com/charmbracelet/soft-serve/pkg/store"19 "github.com/charmbracelet/soft-serve/pkg/store/database"20 "github.com/charmbracelet/soft-serve/pkg/test"21 "github.com/charmbracelet/ssh"22 "github.com/matryer/is"23 gossh "golang.org/x/crypto/ssh"24 _ "modernc.org/sqlite" // sqlite driver25)2627func 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, close := setup(t)32 s.Stderr = os.Stderr33 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: errcheck40 }()41 t.Log("waiting for session to exit")42 _, err = s.Output("test")43 var ee *gossh.ExitMissingError44 is.True(errors.As(err, &ee))45 t.Log("session exited")46 is.NoErr(close())47 })48}4950func 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 return testsession.New(tb, &ssh.Server{80 Handler: ContextMiddleware(cfg, dbx, dbstore, be, log.Default())(bm.MiddlewareWithProgramHandler(SessionHandler)(func(s ssh.Session) {81 _, _, active := s.Pty()82 if !active {83 os.Exit(1)84 }85 s.Exit(0)86 })),87 }, nil), dbx.Close88}