feat: Perform asciicast conversion sanity checks (#3481)
* feat: Perform asciicast conversion sanity checks Check that the conversion to asciicast is done on `exec` or `shell` session program. Unsupported session programs will throw an error.
This commit is contained in:
1 parent
e285a8ef6f
commit
1482f33845
2 files changed
+584
-11
No files matched your search
@@ -55,20 +55,29 @@ func ToAsciicast(ctx context.Context, session *bsr.Session, tmp storage.TempFile
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
// TODO sanity checks before getting the data files:
|
||||
// - check connection summary to see if there was an exec or shell request
|
||||
switch chs := ch.Summary.(type) {
|
||||
case *ssh.ChannelSummary:
|
||||
switch chs.SessionProgram {
|
||||
case ssh.Shell, ssh.Exec:
|
||||
reqScanner, err := ch.OpenRequestScanner(ctx, bsr.Inbound)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
reqScanner, err := ch.OpenRequestScanner(ctx, bsr.Inbound)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
msgScanner, err := ch.OpenMessageScanner(ctx, bsr.Outbound)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
return sshChannelToAsciicast(ctx, reqScanner, msgScanner, tmp, options...)
|
||||
case "":
|
||||
return nil, fmt.Errorf("%s: session program not set for asciicast conversion", op)
|
||||
default:
|
||||
return nil, fmt.Errorf("%s: unsupported %q session program for asciicast conversion", op, chs.SessionProgram)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("%s: unexpected error occurred with channel summary. possibly a malformed Boundary Session Recording", op)
|
||||
}
|
||||
|
||||
msgScanner, err := ch.OpenMessageScanner(ctx, bsr.Outbound)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
return sshChannelToAsciicast(ctx, reqScanner, msgScanner, tmp, options...)
|
||||
default:
|
||||
return nil, fmt.Errorf("%s: %w", op, ErrUnsupportedProtocol)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,564 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package convert_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/bsr"
|
||||
"github.com/hashicorp/boundary/internal/bsr/convert"
|
||||
"github.com/hashicorp/boundary/internal/bsr/internal/fstest"
|
||||
"github.com/hashicorp/boundary/internal/bsr/kms"
|
||||
"github.com/hashicorp/boundary/internal/bsr/ssh"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testChunks(s string, d bsr.Direction, p bsr.Protocol) []bsr.Chunk {
|
||||
ts := time.Date(2023, time.March, 16, 10, 47, 3, 14, time.UTC)
|
||||
|
||||
return []bsr.Chunk{
|
||||
&bsr.HeaderChunk{
|
||||
BaseChunk: &bsr.BaseChunk{
|
||||
Protocol: p,
|
||||
Direction: d,
|
||||
Timestamp: bsr.NewTimestamp(ts),
|
||||
Type: bsr.ChunkHeader,
|
||||
},
|
||||
Compression: bsr.NoCompression,
|
||||
Encryption: bsr.NoEncryption,
|
||||
SessionId: s,
|
||||
},
|
||||
&bsr.EndChunk{
|
||||
BaseChunk: &bsr.BaseChunk{
|
||||
Protocol: p,
|
||||
Direction: d,
|
||||
Timestamp: bsr.NewTimestamp(ts.Add(time.Second)),
|
||||
Type: bsr.ChunkEnd,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func writeToChannels(ctx context.Context, w io.Writer, chunks ...bsr.Chunk) error {
|
||||
w.Write(bsr.Magic.Bytes())
|
||||
enc, err := bsr.NewChunkEncoder(ctx, w, bsr.NoCompression, bsr.NoEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, c := range chunks {
|
||||
_, err := enc.Encode(ctx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestConvert_ToAsciicast_SessionProgram(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
fs := &fstest.MemFS{}
|
||||
tmpfile, err := fstest.NewTempFile(t.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
connectionId := "test_connection"
|
||||
channelId := "test_channel"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
chs bsr.ChannelSummary
|
||||
protocol bsr.Protocol
|
||||
id string
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "exec",
|
||||
id: "01234567890",
|
||||
protocol: ssh.Protocol,
|
||||
chs: &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
SessionProgram: ssh.Exec,
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "shell",
|
||||
id: "11234567890",
|
||||
protocol: ssh.Protocol,
|
||||
chs: &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
SessionProgram: ssh.Shell,
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "unsupported session program - subsystem",
|
||||
id: "21234567890",
|
||||
protocol: ssh.Protocol,
|
||||
chs: &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
SessionProgram: ssh.Subsystem,
|
||||
},
|
||||
wantErr: errors.New("convert.ToAsciicast: unsupported \"subsystem\" session program for asciicast conversion"),
|
||||
},
|
||||
{
|
||||
name: "unsupported session program - not applicable",
|
||||
id: "21234567892",
|
||||
protocol: ssh.Protocol,
|
||||
chs: &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
SessionProgram: ssh.NotApplicable,
|
||||
},
|
||||
wantErr: errors.New("convert.ToAsciicast: unsupported \"not applicable\" session program for asciicast conversion"),
|
||||
},
|
||||
{
|
||||
name: "unsupported session program - none",
|
||||
id: "21234567891",
|
||||
protocol: ssh.Protocol,
|
||||
chs: &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
SessionProgram: ssh.None,
|
||||
},
|
||||
wantErr: errors.New("convert.ToAsciicast: unsupported \"none\" session program for asciicast conversion"),
|
||||
},
|
||||
{
|
||||
name: "nil session program",
|
||||
id: "31234567890",
|
||||
protocol: ssh.Protocol,
|
||||
chs: &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
},
|
||||
wantErr: errors.New("convert.ToAsciicast: session program not set for asciicast conversion"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Setup keys
|
||||
keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), fmt.Sprintf("s_%s", tc.id))
|
||||
require.NoError(t, err)
|
||||
|
||||
keyFn := func(w kms.WrappedKeys) (kms.UnwrappedKeys, error) {
|
||||
u := kms.UnwrappedKeys{
|
||||
BsrKey: keys.BsrKey,
|
||||
PrivKey: keys.PrivKey,
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// Set up session
|
||||
srm := &bsr.SessionRecordingMeta{
|
||||
Id: fmt.Sprintf("sr_%s", tc.id),
|
||||
Protocol: tc.protocol,
|
||||
}
|
||||
sessionMeta := bsr.TestSessionMeta(fmt.Sprintf("s_%s", tc.id))
|
||||
|
||||
sesh, err := bsr.NewSession(ctx, srm, sessionMeta, fs, keys, bsr.WithSupportsMultiplex(true))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, sesh)
|
||||
|
||||
// Encode session summary
|
||||
sesh.EncodeSummary(ctx, &bsr.BaseSessionSummary{
|
||||
Id: channelId,
|
||||
})
|
||||
|
||||
// Set up connection
|
||||
connMeta := &bsr.ConnectionRecordingMeta{Id: connectionId}
|
||||
conn, err := sesh.NewConnection(ctx, connMeta)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, conn)
|
||||
|
||||
// Encode connection summary
|
||||
err = conn.EncodeSummary(ctx, &bsr.BaseConnectionSummary{
|
||||
Id: connectionId,
|
||||
ChannelCount: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Setup Channel
|
||||
chanMeta := &bsr.ChannelRecordingMeta{
|
||||
Id: channelId,
|
||||
Type: "chan",
|
||||
}
|
||||
ch, err := conn.NewChannel(ctx, chanMeta)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, ch)
|
||||
|
||||
// Encode channel summary
|
||||
err = ch.EncodeSummary(ctx, tc.chs)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Write request-inbound.data file
|
||||
requestInboundBsrChunks := testChunks(fmt.Sprintf("s_%s", tc.id), bsr.Inbound, tc.protocol)
|
||||
inW, err := ch.NewRequestsWriter(ctx, bsr.Inbound)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, inW)
|
||||
|
||||
writeToChannels(ctx, inW, requestInboundBsrChunks...)
|
||||
require.NoError(t, err)
|
||||
|
||||
inWC := inW.(io.Closer)
|
||||
inWC.Close()
|
||||
|
||||
// Write message-outbound.data file
|
||||
messageOutboundBsrChunks := testChunks(fmt.Sprintf("s_%s", tc.id), bsr.Outbound, tc.protocol)
|
||||
outW, err := ch.NewMessagesWriter(ctx, bsr.Outbound)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, outW)
|
||||
|
||||
err = writeToChannels(ctx, outW, messageOutboundBsrChunks...)
|
||||
require.NoError(t, err)
|
||||
|
||||
outWC := outW.(io.Closer)
|
||||
outWC.Close()
|
||||
|
||||
ch.Close(ctx)
|
||||
conn.Close(ctx)
|
||||
sesh.Close(ctx)
|
||||
|
||||
opSesh, err := bsr.OpenSession(ctx, srm.Id, fs, keyFn)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, opSesh)
|
||||
|
||||
_, err = convert.ToAsciicast(ctx, opSesh, tmpfile, connectionId, convert.WithChannelId(channelId))
|
||||
if tc.wantErr != nil {
|
||||
require.EqualError(t, err, tc.wantErr.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvert_ToAsciicast_Protocol(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
fs := &fstest.MemFS{}
|
||||
tmpfile, err := fstest.NewTempFile(t.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
connectionId := "test_connection"
|
||||
channelId := "test_channel"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
protocol bsr.Protocol
|
||||
registerSummaryAlloc bool
|
||||
id string
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "unsupported protocol",
|
||||
id: "41234567890",
|
||||
protocol: bsr.Protocol("UNSUPPORTED_PROTOCOL"),
|
||||
registerSummaryAlloc: true,
|
||||
wantErr: errors.New("convert.ToAsciicast: unsupported protocol"),
|
||||
},
|
||||
{
|
||||
name: "BSSH Protocol",
|
||||
id: "51234567890",
|
||||
protocol: ssh.Protocol,
|
||||
registerSummaryAlloc: false,
|
||||
wantErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Setup keys
|
||||
keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), fmt.Sprintf("s_%s", tc.id))
|
||||
require.NoError(t, err)
|
||||
|
||||
keyFn := func(w kms.WrappedKeys) (kms.UnwrappedKeys, error) {
|
||||
u := kms.UnwrappedKeys{
|
||||
BsrKey: keys.BsrKey,
|
||||
PrivKey: keys.PrivKey,
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// Register custom summary alloc func for custom protocol
|
||||
if tc.registerSummaryAlloc {
|
||||
err = bsr.RegisterSummaryAllocFunc(tc.protocol, bsr.ChannelContainer, func(ctx context.Context) bsr.Summary {
|
||||
return &bsr.BaseChannelSummary{Id: channelId, ConnectionRecordingId: connectionId}
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = bsr.RegisterSummaryAllocFunc(tc.protocol, bsr.SessionContainer, func(ctx context.Context) bsr.Summary {
|
||||
return &bsr.BaseSessionSummary{Id: fmt.Sprintf("s_%s", tc.id), ConnectionCount: 1}
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = bsr.RegisterSummaryAllocFunc(tc.protocol, bsr.ConnectionContainer, func(ctx context.Context) bsr.Summary {
|
||||
return &bsr.BaseConnectionSummary{Id: connectionId, ChannelCount: 1}
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Set up session
|
||||
srm := &bsr.SessionRecordingMeta{
|
||||
Id: fmt.Sprintf("sr_%s", tc.id),
|
||||
Protocol: tc.protocol,
|
||||
}
|
||||
sessionMeta := bsr.TestSessionMeta(fmt.Sprintf("s_%s", tc.id))
|
||||
|
||||
sesh, err := bsr.NewSession(ctx, srm, sessionMeta, fs, keys, bsr.WithSupportsMultiplex(true))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, sesh)
|
||||
|
||||
// Encode session summary
|
||||
sesh.EncodeSummary(ctx, &bsr.BaseSessionSummary{
|
||||
Id: channelId,
|
||||
})
|
||||
|
||||
// Set up connection
|
||||
connMeta := &bsr.ConnectionRecordingMeta{Id: connectionId}
|
||||
conn, err := sesh.NewConnection(ctx, connMeta)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, conn)
|
||||
|
||||
// Encode connection summary
|
||||
err = conn.EncodeSummary(ctx, &bsr.BaseConnectionSummary{
|
||||
Id: connectionId,
|
||||
ChannelCount: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Setup Channel
|
||||
chanMeta := &bsr.ChannelRecordingMeta{
|
||||
Id: channelId,
|
||||
Type: "chan",
|
||||
}
|
||||
ch, err := conn.NewChannel(ctx, chanMeta)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, ch)
|
||||
|
||||
// Encode channel summary
|
||||
err = ch.EncodeSummary(ctx, &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
SessionProgram: ssh.Shell,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Write request-inbound.data file
|
||||
requestInboundBsrChunks := testChunks(fmt.Sprintf("s_%s", tc.id), bsr.Inbound, tc.protocol)
|
||||
inW, err := ch.NewRequestsWriter(ctx, bsr.Inbound)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, inW)
|
||||
|
||||
writeToChannels(ctx, inW, requestInboundBsrChunks...)
|
||||
require.NoError(t, err)
|
||||
|
||||
inWC := inW.(io.Closer)
|
||||
inWC.Close()
|
||||
|
||||
// Write message-outbound.data file
|
||||
messageOutboundBsrChunks := testChunks(fmt.Sprintf("s_%s", tc.id), bsr.Outbound, tc.protocol)
|
||||
outW, err := ch.NewMessagesWriter(ctx, bsr.Outbound)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, outW)
|
||||
|
||||
err = writeToChannels(ctx, outW, messageOutboundBsrChunks...)
|
||||
require.NoError(t, err)
|
||||
|
||||
outWC := outW.(io.Closer)
|
||||
outWC.Close()
|
||||
|
||||
ch.Close(ctx)
|
||||
conn.Close(ctx)
|
||||
sesh.Close(ctx)
|
||||
|
||||
opSesh, err := bsr.OpenSession(ctx, srm.Id, fs, keyFn)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, opSesh)
|
||||
|
||||
_, err = convert.ToAsciicast(ctx, opSesh, tmpfile, connectionId, convert.WithChannelId(channelId))
|
||||
if tc.wantErr != nil {
|
||||
require.EqualError(t, err, tc.wantErr.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvert_ToAsciicast_Scanner(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
fs := &fstest.MemFS{}
|
||||
tmpfile, err := fstest.NewTempFile(t.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
connectionId := "test_connection"
|
||||
channelId := "test_channel"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
protocol bsr.Protocol
|
||||
writeRequest bool
|
||||
writeMessage bool
|
||||
id string
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "request and message scanner",
|
||||
id: "61234567890",
|
||||
protocol: ssh.Protocol,
|
||||
writeRequest: true,
|
||||
writeMessage: true,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "missing requests data file",
|
||||
id: "71234567890",
|
||||
protocol: ssh.Protocol,
|
||||
writeRequest: false,
|
||||
writeMessage: true,
|
||||
wantErr: errors.New("convert.ToAsciicast: bsr.(Channel).OpenRequestScanner: file requests-inbound.data does not exist: does not exist"),
|
||||
},
|
||||
{
|
||||
name: "missing messages data file",
|
||||
id: "81234567890",
|
||||
protocol: ssh.Protocol,
|
||||
writeRequest: true,
|
||||
writeMessage: false,
|
||||
wantErr: errors.New("convert.ToAsciicast: bsr.(Channel).OpenMessageScanner: file messages-outbound.data does not exist: does not exist"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Setup keys
|
||||
keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), fmt.Sprintf("s_%s", tc.id))
|
||||
require.NoError(t, err)
|
||||
|
||||
keyFn := func(w kms.WrappedKeys) (kms.UnwrappedKeys, error) {
|
||||
u := kms.UnwrappedKeys{
|
||||
BsrKey: keys.BsrKey,
|
||||
PrivKey: keys.PrivKey,
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// Set up session
|
||||
srm := &bsr.SessionRecordingMeta{
|
||||
Id: fmt.Sprintf("sr_%s", tc.id),
|
||||
Protocol: tc.protocol,
|
||||
}
|
||||
sessionMeta := bsr.TestSessionMeta(fmt.Sprintf("s_%s", tc.id))
|
||||
|
||||
sesh, err := bsr.NewSession(ctx, srm, sessionMeta, fs, keys, bsr.WithSupportsMultiplex(true))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, sesh)
|
||||
|
||||
// Encode session summary
|
||||
sesh.EncodeSummary(ctx, &bsr.BaseSessionSummary{
|
||||
Id: channelId,
|
||||
})
|
||||
|
||||
// Set up connection
|
||||
connMeta := &bsr.ConnectionRecordingMeta{Id: connectionId}
|
||||
conn, err := sesh.NewConnection(ctx, connMeta)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, conn)
|
||||
|
||||
// Encode connection summary
|
||||
err = conn.EncodeSummary(ctx, &bsr.BaseConnectionSummary{
|
||||
Id: connectionId,
|
||||
ChannelCount: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Setup Channel
|
||||
chanMeta := &bsr.ChannelRecordingMeta{
|
||||
Id: channelId,
|
||||
Type: "chan",
|
||||
}
|
||||
ch, err := conn.NewChannel(ctx, chanMeta)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, ch)
|
||||
|
||||
// Encode channel summary
|
||||
err = ch.EncodeSummary(ctx, &ssh.ChannelSummary{
|
||||
ChannelSummary: &bsr.BaseChannelSummary{
|
||||
Id: channelId,
|
||||
ConnectionRecordingId: connectionId,
|
||||
},
|
||||
SessionProgram: ssh.Shell,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
if tc.writeRequest {
|
||||
// Write request-inbound.data file
|
||||
requestInboundBsrChunks := testChunks(fmt.Sprintf("s_%s", tc.id), bsr.Inbound, tc.protocol)
|
||||
inW, err := ch.NewRequestsWriter(ctx, bsr.Inbound)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, inW)
|
||||
|
||||
writeToChannels(ctx, inW, requestInboundBsrChunks...)
|
||||
require.NoError(t, err)
|
||||
|
||||
inWC := inW.(io.Closer)
|
||||
inWC.Close()
|
||||
}
|
||||
|
||||
if tc.writeMessage {
|
||||
// Write message-outbound.data file
|
||||
messageOutboundBsrChunks := testChunks(fmt.Sprintf("s_%s", tc.id), bsr.Outbound, tc.protocol)
|
||||
outW, err := ch.NewMessagesWriter(ctx, bsr.Outbound)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, outW)
|
||||
|
||||
err = writeToChannels(ctx, outW, messageOutboundBsrChunks...)
|
||||
require.NoError(t, err)
|
||||
|
||||
outWC := outW.(io.Closer)
|
||||
outWC.Close()
|
||||
}
|
||||
|
||||
ch.Close(ctx)
|
||||
conn.Close(ctx)
|
||||
sesh.Close(ctx)
|
||||
|
||||
opSesh, err := bsr.OpenSession(ctx, srm.Id, fs, keyFn)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, opSesh)
|
||||
|
||||
_, err = convert.ToAsciicast(ctx, opSesh, tmpfile, connectionId, convert.WithChannelId(channelId))
|
||||
if tc.wantErr != nil {
|
||||
require.EqualError(t, err, tc.wantErr.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user