github.com/hashicorp/go-plugin@v1.6.0/client_posix_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  //go:build !windows
     5  // +build !windows
     6  
     7  package plugin
     8  
     9  import (
    10  	"os"
    11  	"reflect"
    12  	"syscall"
    13  	"testing"
    14  	"time"
    15  )
    16  
    17  func TestClient_testInterfaceReattach(t *testing.T) {
    18  	// Setup the process for daemonization
    19  	process := helperProcess("test-interface-daemon")
    20  	if process.SysProcAttr == nil {
    21  		process.SysProcAttr = &syscall.SysProcAttr{}
    22  	}
    23  	process.SysProcAttr.Setsid = true
    24  	syscall.Umask(0)
    25  
    26  	c := NewClient(&ClientConfig{
    27  		Cmd:             process,
    28  		HandshakeConfig: testHandshake,
    29  		Plugins:         testPluginMap,
    30  	})
    31  
    32  	// Start it so we can get the reattach info
    33  	if _, err := c.Start(); err != nil {
    34  		t.Fatalf("err should be nil, got %s", err)
    35  	}
    36  
    37  	// New client with reattach info
    38  	reattach := c.ReattachConfig()
    39  	if reattach == nil {
    40  		c.Kill()
    41  		t.Fatal("reattach config should be non-nil")
    42  	}
    43  
    44  	// Find the process and defer a kill so we know it is gone
    45  	p, err := os.FindProcess(reattach.Pid)
    46  	if err != nil {
    47  		c.Kill()
    48  		t.Fatalf("couldn't find process: %s", err)
    49  	}
    50  	defer p.Kill()
    51  
    52  	// Reattach
    53  	c = NewClient(&ClientConfig{
    54  		Reattach:        reattach,
    55  		HandshakeConfig: testHandshake,
    56  		Plugins:         testPluginMap,
    57  	})
    58  
    59  	// Start shouldn't error
    60  	if _, err := c.Start(); err != nil {
    61  		t.Fatalf("err: %s", err)
    62  	}
    63  
    64  	// It should still be alive
    65  	time.Sleep(1 * time.Second)
    66  	if c.Exited() {
    67  		t.Fatal("should not be exited")
    68  	}
    69  
    70  	// Grab the RPC client
    71  	client, err := c.Client()
    72  	if err != nil {
    73  		t.Fatalf("err should be nil, got %s", err)
    74  	}
    75  
    76  	// Grab the impl
    77  	raw, err := client.Dispense("test")
    78  	if err != nil {
    79  		t.Fatalf("err should be nil, got %s", err)
    80  	}
    81  
    82  	impl, ok := raw.(testInterface)
    83  	if !ok {
    84  		t.Fatalf("bad: %#v", raw)
    85  	}
    86  
    87  	result := impl.Double(21)
    88  	if result != 42 {
    89  		t.Fatalf("bad: %#v", result)
    90  	}
    91  
    92  	// Test the resulting reattach config
    93  	reattach2 := c.ReattachConfig()
    94  	if reattach2 == nil {
    95  		t.Fatal("reattach from reattached should not be nil")
    96  	}
    97  	if !reflect.DeepEqual(reattach, reattach2) {
    98  		t.Fatalf("bad: %#v", reattach)
    99  	}
   100  
   101  	// Kill it
   102  	c.Kill()
   103  
   104  	// Test that it knows it is exited
   105  	if !c.Exited() {
   106  		t.Fatal("should say client has exited")
   107  	}
   108  }