github.com/hashicorp/go-plugin@v1.6.0/rpc_client_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package plugin 5 6 import ( 7 "bytes" 8 "io" 9 "os" 10 "sync" 11 "testing" 12 "time" 13 14 hclog "github.com/hashicorp/go-hclog" 15 ) 16 17 func TestClient_App(t *testing.T) { 18 pluginLogger := hclog.New(&hclog.LoggerOptions{ 19 Level: hclog.Trace, 20 Output: os.Stderr, 21 JSONFormat: true, 22 }) 23 24 testPlugin := &testInterfaceImpl{ 25 logger: pluginLogger, 26 } 27 28 client, _ := TestPluginRPCConn(t, map[string]Plugin{ 29 "test": &testInterfacePlugin{Impl: testPlugin}, 30 }, nil) 31 defer client.Close() 32 33 raw, err := client.Dispense("test") 34 if err != nil { 35 t.Fatalf("err: %s", err) 36 } 37 38 impl, ok := raw.(testInterface) 39 if !ok { 40 t.Fatalf("bad: %#v", raw) 41 } 42 43 result := impl.Double(21) 44 if result != 42 { 45 t.Fatalf("bad: %#v", result) 46 } 47 } 48 49 func TestClient_syncStreams(t *testing.T) { 50 // Create streams for the server that we can talk to 51 stdout_r, stdout_w := io.Pipe() 52 stderr_r, stderr_w := io.Pipe() 53 54 client, _ := TestPluginRPCConn(t, map[string]Plugin{}, &TestOptions{ 55 ServerStdout: stdout_r, 56 ServerStderr: stderr_r, 57 }) 58 59 // Start the data copying 60 var stdout_out, stderr_out safeBuffer 61 stdout := &safeBuffer{ 62 b: bytes.NewBufferString("stdouttest"), 63 } 64 stderr := &safeBuffer{ 65 b: bytes.NewBufferString("stderrtest"), 66 } 67 go client.SyncStreams(&stdout_out, &stderr_out) 68 go io.Copy(stdout_w, stdout) 69 go io.Copy(stderr_w, stderr) 70 71 // Unfortunately I can't think of a better way to make sure all the 72 // copies above go through so let's just exit. 73 time.Sleep(100 * time.Millisecond) 74 75 // Close everything, and lets test the result 76 client.Close() 77 stdout_w.Close() 78 stderr_w.Close() 79 80 if v := stdout_out.String(); v != "stdouttest" { 81 t.Fatalf("bad: %q", v) 82 } 83 if v := stderr_out.String(); v != "stderrtest" { 84 t.Fatalf("bad: %q", v) 85 } 86 } 87 88 type safeBuffer struct { 89 sync.Mutex 90 b *bytes.Buffer 91 } 92 93 func (s *safeBuffer) Write(p []byte) (n int, err error) { 94 s.Lock() 95 defer s.Unlock() 96 if s.b == nil { 97 s.b = new(bytes.Buffer) 98 } 99 return s.b.Write(p) 100 } 101 102 func (s *safeBuffer) Read(p []byte) (n int, err error) { 103 s.Lock() 104 defer s.Unlock() 105 if s.b == nil { 106 s.b = new(bytes.Buffer) 107 } 108 return s.b.Read(p) 109 } 110 111 func (s *safeBuffer) String() string { 112 s.Lock() 113 defer s.Unlock() 114 if s.b == nil { 115 s.b = new(bytes.Buffer) 116 } 117 return s.b.String() 118 }