swupd: add external reader and writer

These types enable using external programs as filters. This will be
used to call external compression/decompression programs.

Signed-off-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
This commit is contained in:
Caio Marcelo de Oliveira Filho
2018-01-05 16:16:56 -08:00
committed by tmarcu
parent 4976308c8a
commit 2ef8badef4
2 changed files with 147 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
package swupd
import (
"io"
"os/exec"
)
type externalWriter struct {
cmd *exec.Cmd
input io.WriteCloser
}
// newExternalWriter creates a Writer that will filter the contents in the
// external program and then write to w.
func newExternalWriter(w io.Writer, program string, args ...string) (*externalWriter, error) {
cmd := exec.Command(program, args...)
input, err := cmd.StdinPipe()
if err != nil {
return nil, err
}
cmd.Stdout = w
err = cmd.Start()
if err != nil {
input.Close()
return nil, err
}
return &externalWriter{cmd, input}, nil
}
func (ew *externalWriter) Write(p []byte) (int, error) {
return ew.input.Write(p)
}
func (ew *externalWriter) Close() error {
err := ew.input.Close()
if err != nil {
return err
}
return ew.cmd.Wait()
}
type externalReader struct {
cmd *exec.Cmd
output io.ReadCloser
}
// newExternalReader creates a Reader that will filter the contents of r in the
// external program before returning it.
func newExternalReader(r io.Reader, program string, args ...string) (*externalReader, error) {
cmd := exec.Command(program, args...)
cmd.Stdin = r
output, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
err = cmd.Start()
if err != nil {
output.Close()
return nil, err
}
return &externalReader{cmd, output}, nil
}
func (er *externalReader) Read(p []byte) (int, error) {
return er.output.Read(p)
}
func (er *externalReader) Close() error {
err := er.output.Close()
if err != nil {
return err
}
return er.cmd.Wait()
}
+73
View File
@@ -0,0 +1,73 @@
package swupd
import (
"bytes"
"io/ioutil"
"os/exec"
"strings"
"testing"
)
func TestExternalWriter(t *testing.T) {
tr, err := exec.LookPath("tr")
if err != nil {
if err == exec.ErrNotFound {
t.Skip("couldn't find tr program used for test")
}
t.Fatal(err)
}
var output bytes.Buffer
w, err := newExternalWriter(&output, tr, "e", "a")
if err != nil {
t.Fatal(err)
}
input := "Hello, world!"
expected := strings.Replace(input, "e", "a", -1)
_, err = w.Write([]byte(input))
if err != nil {
t.Fatal(err)
}
err = w.Close()
if err != nil {
t.Fatal(err)
}
if output.String() != expected {
t.Fatalf("got %q, but want %q", output.String(), expected)
}
}
func TestExternalReader(t *testing.T) {
tr, err := exec.LookPath("tr")
if err != nil {
if err == exec.ErrNotFound {
t.Skip("couldn't find tr program used for test")
}
t.Fatal(err)
}
input := "Hello, world!"
expected := strings.Replace(input, "e", "a", -1)
r, err := newExternalReader(strings.NewReader(input), tr, "e", "a")
if err != nil {
t.Fatal(err)
}
output, err := ioutil.ReadAll(r)
if err != nil {
t.Fatal(err)
}
if string(output) != expected {
t.Fatalf("got %q, but want %q", string(output), expected)
}
err = r.Close()
if err != nil {
t.Fatal(err)
}
}