1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
Description: Fix racy tests
This patch is a re-work of upstream commit 4b17561, available at
<https://github.com/hashicorp/go-plugin/commit/4b17561>.
.
The commit was reworked to apply on the current version.
.
Please drop this patch as soon as the package version reaches 4b17561,
from February 7th, 2018.
Author: Arnaud Rebillout <arnaud.rebillout@collabora.com>
Forwarded: not-needed
Last-Update: 2018-07-09
---
client_test.go | 11 +++++++++++
rpc_client_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++--------
testing.go | 23 ++++++++++++++++++++++-
3 files changed, 79 insertions(+), 9 deletions(-)
--- a/rpc_client_test.go
+++ b/rpc_client_test.go
@@ -3,6 +3,7 @@
import (
"bytes"
"io"
+ "sync"
"testing"
"time"
)
@@ -10,7 +11,7 @@
func TestClient_App(t *testing.T) {
client, _ := TestPluginRPCConn(t, map[string]Plugin{
"test": new(testInterfacePlugin),
- })
+ }, nil)
defer client.Close()
raw, err := client.Dispense("test")
@@ -30,18 +31,23 @@
}
func TestClient_syncStreams(t *testing.T) {
- client, server := TestPluginRPCConn(t, map[string]Plugin{})
-
// Create streams for the server that we can talk to
stdout_r, stdout_w := io.Pipe()
stderr_r, stderr_w := io.Pipe()
- server.Stdout = stdout_r
- server.Stderr = stderr_r
+
+ client, _ := TestPluginRPCConn(t, map[string]Plugin{}, &TestOptions{
+ ServerStdout: stdout_r,
+ ServerStderr: stderr_r,
+ })
// Start the data copying
- var stdout_out, stderr_out bytes.Buffer
- stdout := bytes.NewBufferString("stdouttest")
- stderr := bytes.NewBufferString("stderrtest")
+ var stdout_out, stderr_out safeBuffer
+ stdout := &safeBuffer{
+ b: bytes.NewBufferString("stdouttest"),
+ }
+ stderr := &safeBuffer{
+ b: bytes.NewBufferString("stderrtest"),
+ }
go client.SyncStreams(&stdout_out, &stderr_out)
go io.Copy(stdout_w, stdout)
go io.Copy(stderr_w, stderr)
@@ -62,3 +68,35 @@
t.Fatalf("bad: %s", v)
}
}
+
+type safeBuffer struct {
+ sync.Mutex
+ b *bytes.Buffer
+}
+
+func (s *safeBuffer) Write(p []byte) (n int, err error) {
+ s.Lock()
+ defer s.Unlock()
+ if s.b == nil {
+ s.b = new(bytes.Buffer)
+ }
+ return s.b.Write(p)
+}
+
+func (s *safeBuffer) Read(p []byte) (n int, err error) {
+ s.Lock()
+ defer s.Unlock()
+ if s.b == nil {
+ s.b = new(bytes.Buffer)
+ }
+ return s.b.Read(p)
+}
+
+func (s *safeBuffer) String() string {
+ s.Lock()
+ defer s.Unlock()
+ if s.b == nil {
+ s.b = new(bytes.Buffer)
+ }
+ return s.b.String()
+}
--- a/testing.go
+++ b/testing.go
@@ -2,6 +2,7 @@
import (
"bytes"
+ "io"
"net"
"net/rpc"
"testing"
@@ -9,6 +10,18 @@
"google.golang.org/grpc"
)
+// TestOptions allows specifying options that can affect the behavior of the
+// test functions
+type TestOptions struct {
+ //ServerStdout causes the given value to be used in place of a blank buffer
+ //for RPCServer's Stdout
+ ServerStdout io.ReadCloser
+
+ //ServerStderr causes the given value to be used in place of a blank buffer
+ //for RPCServer's Stderr
+ ServerStderr io.ReadCloser
+}
+
// The testing file contains test helpers that you can use outside of
// this package for making it easier to test plugins themselves.
@@ -60,12 +73,20 @@
// TestPluginRPCConn returns a plugin RPC client and server that are connected
// together and configured.
-func TestPluginRPCConn(t *testing.T, ps map[string]Plugin) (*RPCClient, *RPCServer) {
+func TestPluginRPCConn(t *testing.T, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) {
// Create two net.Conns we can use to shuttle our control connection
clientConn, serverConn := TestConn(t)
// Start up the server
server := &RPCServer{Plugins: ps, Stdout: new(bytes.Buffer), Stderr: new(bytes.Buffer)}
+ if opts != nil {
+ if opts.ServerStdout != nil {
+ server.Stdout = opts.ServerStdout
+ }
+ if opts.ServerStderr != nil {
+ server.Stderr = opts.ServerStderr
+ }
+ }
go server.ServeConn(serverConn)
// Connect the client to the server
|