Add doc and tests for ioconn package (#291)
This commit is contained in:
parent
9fee039d93
commit
050a9baadb
6 changed files with 120 additions and 1 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
31
libplugin/ioconn/cmd_test.go
Normal file
31
libplugin/ioconn/cmd_test.go
Normal 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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
29
libplugin/ioconn/conn_test.go
Normal file
29
libplugin/ioconn/conn_test.go
Normal 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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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},
|
||||
|
|
|
|||
35
libplugin/ioconn/listener_test.go
Normal file
35
libplugin/ioconn/listener_test.go
Normal 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))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue