Add doc and tests for ioconn package (#291)

This commit is contained in:
Boshi Lian 2023-12-25 15:01:40 -08:00 committed by GitHub
parent 9fee039d93
commit 050a9baadb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 120 additions and 1 deletions

View file

@ -11,6 +11,10 @@ type cmdconn struct {
cmd *exec.Cmd
}
// Close closes the cmdconn and releases any associated resources.
// It first closes the underlying connection and then kills the process if it is running.
// If an error occurs during the closing of the connection, that error is returned.
// If the process is running and cannot be killed, an error is returned.
func (c *cmdconn) Close() error {
err := c.conn.Close()
@ -21,6 +25,11 @@ func (c *cmdconn) Close() error {
return err
}
// DialCmd is a function that establishes a connection to a command's standard input, output, and error streams.
// It takes a *exec.Cmd as input and returns a net.Conn, io.ReadCloser, and error.
// The net.Conn represents the connection to the command's standard input and output streams.
// The io.ReadCloser represents the command's standard error stream.
// The error represents any error that occurred during the connection establishment.
func DialCmd(cmd *exec.Cmd) (net.Conn, io.ReadCloser, error) {
in, err := cmd.StdoutPipe()
if err != nil {

View file

@ -0,0 +1,31 @@
//go:build linux
package ioconn_test
import (
"os/exec"
"testing"
"github.com/tg123/sshpiper/libplugin/ioconn"
)
func TestDialCmd(t *testing.T) {
cmd := exec.Command("cat")
conn, _, err := ioconn.DialCmd(cmd)
if err != nil {
t.Errorf("DialCmd returned an error: %v", err)
}
defer conn.Close()
go func() {
_, _ = conn.Write([]byte("world"))
}()
buf := make([]byte, 5)
_, _ = conn.Read(buf)
if string(buf) != "world" {
t.Errorf("unexpected string read: %v", string(buf))
}
}

View file

@ -22,7 +22,19 @@ type conn struct {
out io.WriteCloser
}
// Dial creates a new network connection using the provided input and output streams.
// It returns a net.Conn interface and an error, if any.
// The input stream is used for reading data from the connection,
// and the output stream is used for writing data to the connection.
func Dial(in io.ReadCloser, out io.WriteCloser) (net.Conn, error) {
if in == nil {
return nil, fmt.Errorf("input stream is nil")
}
if out == nil {
return nil, fmt.Errorf("output stream is nil")
}
return dial(in, out), nil
}
@ -55,7 +67,7 @@ func (c *conn) Close() error {
}
if outerr == nil {
return outerr
return inerr
}
return fmt.Errorf("io close error in: %v, out: %v", inerr, outerr)

View file

@ -0,0 +1,29 @@
package ioconn_test
import (
"io"
"testing"
"github.com/tg123/sshpiper/libplugin/ioconn"
)
func TestDial(t *testing.T) {
in, out := io.Pipe()
conn, err := ioconn.Dial(in, out)
if err != nil {
t.Errorf("Dial returned an error: %v", err)
}
defer conn.Close()
go func() {
_, _ = conn.Write([]byte("hello"))
}()
buf := make([]byte, 5)
_, _ = conn.Read(buf)
if string(buf) != "hello" {
t.Errorf("unexpected string read: %v", string(buf))
}
}

View file

@ -26,6 +26,9 @@ func (l *singleConnListener) Close() error {
return l.conn.Close()
}
// ListenFromSingleIO creates a net.Listener from a single input/output connection.
// It takes an io.ReadCloser and an io.WriteCloser as parameters and returns a net.Listener and an error.
// The returned net.Listener can be used to accept incoming connections.
func ListenFromSingleIO(in io.ReadCloser, out io.WriteCloser) (net.Listener, error) {
l := &singleConnListener{
conn{in, out},

View file

@ -0,0 +1,35 @@
package ioconn_test
import (
"io"
"testing"
"github.com/tg123/sshpiper/libplugin/ioconn"
)
func TestListenFromSingleIO(t *testing.T) {
in, out := io.Pipe()
l, err := ioconn.ListenFromSingleIO(in, out)
if err != nil {
t.Errorf("ListenFromSingleIO returned an error: %v", err)
}
conn, err := l.Accept()
if err != nil {
t.Errorf("Accept returned an error: %v", err)
}
defer conn.Close()
defer l.Close()
go func() {
_, _ = conn.Write([]byte("hello"))
}()
buf := make([]byte, 5)
_, _ = conn.Read(buf)
if string(buf) != "hello" {
t.Errorf("unexpected string read: %v", string(buf))
}
}