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