github.com/Jeffail/benthos/v3@v3.65.0/lib/input/subprocess_test.go (about) 1 package input 2 3 import ( 4 "os" 5 "path" 6 "testing" 7 "time" 8 9 "github.com/Jeffail/benthos/v3/lib/log" 10 "github.com/Jeffail/benthos/v3/lib/metrics" 11 "github.com/Jeffail/benthos/v3/lib/response" 12 "github.com/Jeffail/benthos/v3/lib/types" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func testProgram(t *testing.T, program string) string { 18 t.Helper() 19 20 dir := t.TempDir() 21 22 pathStr := path.Join(dir, "main.go") 23 require.NoError(t, os.WriteFile(pathStr, []byte(program), 0o666)) 24 25 return pathStr 26 } 27 28 func readMsg(t *testing.T, tranChan <-chan types.Transaction) types.Message { 29 t.Helper() 30 select { 31 case tran := <-tranChan: 32 select { 33 case tran.ResponseChan <- response.NewAck(): 34 case <-time.After(time.Second): 35 t.Fatal("timed out") 36 } 37 return tran.Payload 38 case <-time.After(time.Second * 5): 39 } 40 t.Fatal("timed out") 41 return nil 42 } 43 44 func TestSubprocessBasic(t *testing.T) { 45 filePath := testProgram(t, `package main 46 47 import ( 48 "fmt" 49 ) 50 51 func main() { 52 fmt.Println("foo") 53 fmt.Println("bar") 54 fmt.Println("baz") 55 } 56 `) 57 58 conf := NewConfig() 59 conf.Type = TypeSubprocess 60 conf.Subprocess.Name = "go" 61 conf.Subprocess.Args = []string{"run", filePath} 62 63 i, err := New(conf, nil, log.Noop(), metrics.Noop()) 64 require.NoError(t, err) 65 66 msg := readMsg(t, i.TransactionChan()) 67 assert.Equal(t, 1, msg.Len()) 68 assert.Equal(t, "foo", string(msg.Get(0).Get())) 69 70 msg = readMsg(t, i.TransactionChan()) 71 assert.Equal(t, 1, msg.Len()) 72 assert.Equal(t, "bar", string(msg.Get(0).Get())) 73 74 msg = readMsg(t, i.TransactionChan()) 75 assert.Equal(t, 1, msg.Len()) 76 assert.Equal(t, "baz", string(msg.Get(0).Get())) 77 78 select { 79 case _, open := <-i.TransactionChan(): 80 assert.False(t, open) 81 case <-time.After(time.Second): 82 t.Error("timed out") 83 } 84 } 85 86 func TestSubprocessRestarted(t *testing.T) { 87 filePath := testProgram(t, `package main 88 89 import ( 90 "fmt" 91 ) 92 93 func main() { 94 fmt.Println("foo") 95 fmt.Println("bar") 96 fmt.Println("baz") 97 } 98 `) 99 100 conf := NewConfig() 101 conf.Type = TypeSubprocess 102 conf.Subprocess.Name = "go" 103 conf.Subprocess.RestartOnExit = true 104 conf.Subprocess.Args = []string{"run", filePath} 105 106 i, err := New(conf, nil, log.Noop(), metrics.Noop()) 107 require.NoError(t, err) 108 109 msg := readMsg(t, i.TransactionChan()) 110 assert.Equal(t, 1, msg.Len()) 111 assert.Equal(t, "foo", string(msg.Get(0).Get())) 112 113 msg = readMsg(t, i.TransactionChan()) 114 assert.Equal(t, 1, msg.Len()) 115 assert.Equal(t, "bar", string(msg.Get(0).Get())) 116 117 msg = readMsg(t, i.TransactionChan()) 118 assert.Equal(t, 1, msg.Len()) 119 assert.Equal(t, "baz", string(msg.Get(0).Get())) 120 121 msg = readMsg(t, i.TransactionChan()) 122 assert.Equal(t, 1, msg.Len()) 123 assert.Equal(t, "foo", string(msg.Get(0).Get())) 124 125 msg = readMsg(t, i.TransactionChan()) 126 assert.Equal(t, 1, msg.Len()) 127 assert.Equal(t, "bar", string(msg.Get(0).Get())) 128 129 msg = readMsg(t, i.TransactionChan()) 130 assert.Equal(t, 1, msg.Len()) 131 assert.Equal(t, "baz", string(msg.Get(0).Get())) 132 133 i.CloseAsync() 134 require.NoError(t, i.WaitForClose(time.Second)) 135 } 136 137 func TestSubprocessCloseInBetween(t *testing.T) { 138 filePath := testProgram(t, `package main 139 140 import ( 141 "fmt" 142 ) 143 144 func main() { 145 i := 0 146 for { 147 fmt.Printf("foo:%v\n", i) 148 i++ 149 } 150 } 151 `) 152 153 conf := NewConfig() 154 conf.Type = TypeSubprocess 155 conf.Subprocess.Name = "go" 156 conf.Subprocess.Args = []string{"run", filePath} 157 158 i, err := New(conf, nil, log.Noop(), metrics.Noop()) 159 require.NoError(t, err) 160 161 msg := readMsg(t, i.TransactionChan()) 162 assert.Equal(t, 1, msg.Len()) 163 assert.Equal(t, "foo:0", string(msg.Get(0).Get())) 164 165 msg = readMsg(t, i.TransactionChan()) 166 assert.Equal(t, 1, msg.Len()) 167 assert.Equal(t, "foo:1", string(msg.Get(0).Get())) 168 169 i.CloseAsync() 170 require.NoError(t, i.WaitForClose(time.Second)) 171 }