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  }