func TestProcess_MissedKeepaliveInfo(t *testing.T) { abortCalled := make(chan struct{}) aborted := func() { close(abortCalled) } cmd := cmd_test.NewCommandHelper() l := log.New(os.Stderr, "[TestProcess_MissedKeepalive] ", log.LstdFlags) p := kapacitor.NewUDFProcess(cmd, l, 2, aborted) p.Start() p.Info() // Since the keepalive is missed, the process should abort on its own. for range cmd.Requests { } select { case <-abortCalled: case <-time.After(time.Second * 20): t.Error("expected abort callback to be called") } close(cmd.Responses) if err := <-cmd.ErrC; err != nil { t.Error(err) } }
func TestProcess_StartInitStop(t *testing.T) { cmd := cmd_test.NewCommandHelper() l := log.New(os.Stderr, "[TestProcess_StartStop] ", log.LstdFlags) p := kapacitor.NewUDFProcess(cmd, l, 0, nil) go func() { req := <-cmd.Requests _, ok := req.Message.(*udf.Request_Init) if !ok { t.Errorf("expected init message got %T", req.Message) } res := &udf.Response{ Message: &udf.Response_Init{ Init: &udf.InitResponse{ Success: true, }, }, } cmd.Responses <- res close(cmd.Responses) }() p.Start() err := p.Init(nil) if err != nil { t.Fatal(err) } p.Stop() // read all requests and wait till the chan is closed for range cmd.Requests { } if err := <-cmd.ErrC; err != nil { t.Error(err) } }
func TestProcess_Keepalive(t *testing.T) { cmd := cmd_test.NewCommandHelper() l := log.New(os.Stderr, "[TestProcess_Keepalive] ", log.LstdFlags) p := kapacitor.NewUDFProcess(cmd, l, time.Millisecond*10, nil) p.Start() p.Init(nil) req := <-cmd.Requests _, ok := req.Message.(*udf.Request_Init) if !ok { t.Error("expected init message") } select { case req = <-cmd.Requests: case <-time.After(time.Second): t.Fatal("expected keepalive message") } if req == nil { t.Fatal("expected keepalive message got nil") } _, ok = req.Message.(*udf.Request_Keepalive) if !ok { t.Errorf("expected keepalive message got %T", req.Message) } close(cmd.Responses) p.Stop() // read all requests and wait till the chan is closed for range cmd.Requests { } if err := <-cmd.ErrC; err != nil { t.Error(err) } }
func newUDFProcess(name string) (*kapacitor.UDFProcess, *udf_test.IO) { uio := udf_test.NewIO() cmd := newTestCommander(uio) l := log.New(os.Stderr, fmt.Sprintf("[%s] ", name), log.LstdFlags) u := kapacitor.NewUDFProcess(cmd, l, 0, nil) return u, uio }
func TestProcess_StartStop(t *testing.T) { cmd := cmd_test.NewCommandHelper() l := log.New(os.Stderr, "[TestProcess_StartStop] ", log.LstdFlags) p := kapacitor.NewUDFProcess(cmd, l, 0, nil) p.Start() close(cmd.Responses) p.Stop() // read all requests and wait till the chan is closed for range cmd.Requests { } if err := <-cmd.ErrC; err != nil { t.Error(err) } }
func (s *Service) loadProcessInfo(f FunctionConfig) (kapacitor.UDFProcessInfo, error) { env := os.Environ() for k, v := range f.Env { env = append(env, fmt.Sprintf("%s=%s", k, v)) } commander := command.CommandInfo{ Prog: f.Prog, Args: f.Args, Env: env, } p := kapacitor.NewUDFProcess(commander, s.logger, time.Duration(f.Timeout), nil) err := p.Start() if err != nil { return kapacitor.UDFProcessInfo{}, err } defer p.Stop() return p.Info() }
func TestProcess_StartInitAbort(t *testing.T) { cmd := cmd_test.NewCommandHelper() l := log.New(os.Stderr, "[TestProcess_StartInfoAbort] ", log.LstdFlags) p := kapacitor.NewUDFProcess(cmd, l, 0, nil) p.Start() expErr := errors.New("explicit abort") go func() { req := <-cmd.Requests _, ok := req.Message.(*udf.Request_Init) if !ok { t.Error("expected init message") } p.Abort(expErr) close(cmd.Responses) }() err := p.Init(nil) if err != expErr { t.Fatal("expected explicit abort error") } }
func TestProcess_StartInfoStop(t *testing.T) { cmd := cmd_test.NewCommandHelper() l := log.New(os.Stderr, "[TestProcess_StartInfoStop] ", log.LstdFlags) p := kapacitor.NewUDFProcess(cmd, l, 0, nil) go func() { req := <-cmd.Requests _, ok := req.Message.(*udf.Request_Info) if !ok { t.Errorf("expected info message got %T", req.Message) } res := &udf.Response{ Message: &udf.Response_Info{ Info: &udf.InfoResponse{ Wants: udf.EdgeType_STREAM, Provides: udf.EdgeType_BATCH, }, }, } cmd.Responses <- res close(cmd.Responses) }() p.Start() info, err := p.Info() if err != nil { t.Fatal(err) } if exp, got := pipeline.StreamEdge, info.Wants; got != exp { t.Errorf("unexpected info.Wants got %v exp %v", got, exp) } if exp, got := pipeline.BatchEdge, info.Provides; got != exp { t.Errorf("unexpected info.Provides got %v exp %v", got, exp) } p.Stop() // read all requests and wait till the chan is closed for range cmd.Requests { } if err := <-cmd.ErrC; err != nil { t.Error(err) } }
func (s *Service) Create( name string, l *log.Logger, abortCallback func(), ) (udf.Interface, error) { conf, ok := s.configs[name] if !ok { return nil, fmt.Errorf("no such UDF %s", name) } if conf.Socket != "" { // Create socket UDF return kapacitor.NewUDFSocket( kapacitor.NewSocketConn(conf.Socket), l, time.Duration(conf.Timeout), abortCallback, ), nil } else { // Create process UDF env := os.Environ() for k, v := range conf.Env { env = append(env, fmt.Sprintf("%s=%s", k, v)) } commander := kapacitor.CommandInfo{ Prog: conf.Prog, Args: conf.Args, Env: env, } return kapacitor.NewUDFProcess( commander, l, time.Duration(conf.Timeout), abortCallback, ), nil } }
func TestProcess_SnapshotRestore(t *testing.T) { cmd := cmd_test.NewCommandHelper() l := log.New(os.Stderr, "[TestProcess_SnapshotRestore] ", log.LstdFlags) p := kapacitor.NewUDFProcess(cmd, l, 0, nil) go func() { // Init req := <-cmd.Requests _, ok := req.Message.(*udf.Request_Init) if !ok { t.Error("expected init message") } cmd.Responses <- &udf.Response{ Message: &udf.Response_Init{ Init: &udf.InitResponse{Success: true}, }, } // Snapshot req = <-cmd.Requests if req == nil { t.Fatal("expected snapshot message got nil") } _, ok = req.Message.(*udf.Request_Snapshot) if !ok { t.Errorf("expected snapshot message got %T", req.Message) } data := []byte{42} cmd.Responses <- &udf.Response{ Message: &udf.Response_Snapshot{ Snapshot: &udf.SnapshotResponse{data}, }, } // Restore req = <-cmd.Requests if req == nil { t.Fatal("expected restore message got nil") } restore, ok := req.Message.(*udf.Request_Restore) if !ok { t.Errorf("expected restore message got %T", req.Message) } if !reflect.DeepEqual(data, restore.Restore.Snapshot) { t.Errorf("unexpected restore snapshot got %v exp %v", restore.Restore.Snapshot, data) } cmd.Responses <- &udf.Response{ Message: &udf.Response_Restore{ Restore: &udf.RestoreResponse{Success: true}, }, } close(cmd.Responses) }() p.Start() p.Init(nil) snapshot, err := p.Snapshot() if err != nil { t.Fatal(err) } err = p.Restore(snapshot) if err != nil { t.Fatal(err) } p.Stop() // read all requests and wait till the chan is closed for range cmd.Requests { } if err := <-cmd.ErrC; err != nil { t.Error(err) } }