func (s *ServerSuite) TestStartHandleStop() { // Start taskHandler := func(a *acomm.Request) (interface{}, *url.URL, error) { return nil, nil, nil } s.server.RegisterTask("foobar", taskHandler) if !s.NoError(s.server.Start(), "failed to start server") { return } time.Sleep(time.Second) // Stop defer s.server.Stop() // Handle request tracker := s.server.Tracker() handled := make(chan struct{}) respHandler := func(req *acomm.Request, resp *acomm.Response) { close(handled) } req, _ := acomm.NewRequest("foobar", tracker.URL().String(), struct{}{}, respHandler, respHandler) providerSocket, _ := url.ParseRequestURI("unix://" + s.server.TaskSocketPath("foobar")) if !s.NoError(s.server.Tracker().TrackRequest(req, 5*time.Second)) { return } if !s.NoError(acomm.Send(providerSocket, req)) { return } <-handled }
func (s *RequestTestSuite) TestNewRequest() { task := "foobar" args := map[string]string{ "foo": "bar", } sh, eh, _ := generateHandlers() tests := []struct { description string task string responseHook string args interface{} sh acomm.ResponseHandler eh acomm.ResponseHandler expectedErr bool }{ {"missing response hook", task, "", args, sh, eh, true}, {"invalid response hook", task, "asdf", args, sh, eh, true}, {"missing args", task, "unix://asdf", nil, sh, eh, false}, {"unix hook and args", task, "unix://asdf", args, sh, eh, false}, {"http hook and args", task, "http://asdf", args, sh, eh, false}, {"https hook and args", task, "https://asdf", args, sh, eh, false}, {"unix hook, args, no handlers", task, "unix://asdf", args, nil, nil, false}, {"unix hook, args, sh handler", task, "unix://asdf", args, sh, nil, false}, {"unix hook, args, eh handler", task, "unix://asdf", args, nil, eh, false}, {"missing task ", "", "unix://asdf", args, sh, eh, true}, } for _, test := range tests { msg := testMsgFunc(test.description) req, err := acomm.NewRequest(test.task, test.responseHook, test.args, test.sh, test.eh) if test.expectedErr { s.Error(err, msg("should have failed")) s.Nil(req, msg("should not have returned a request")) } else { if !s.NoError(err, msg("should have succeeded")) { s.T().Log(msg(err.Error())) continue } if !s.NotNil(req, msg("should have returned a request")) { continue } s.NotEmpty(req.ID, msg("should have set an ID")) s.Equal(test.task, req.Task, msg("should have set the task")) s.Equal(test.responseHook, req.ResponseHook.String(), msg("should have set the response hook")) var args map[string]string s.NoError(req.UnmarshalArgs(&args)) if test.args == nil { s.Nil(args, msg("should have nil arguments")) } else { s.Equal(test.args, args, msg("should have set the arguments")) } s.Equal(reflect.ValueOf(test.sh).Pointer(), reflect.ValueOf(req.SuccessHandler).Pointer(), msg("should have set success handler")) s.Equal(reflect.ValueOf(test.eh).Pointer(), reflect.ValueOf(req.ErrorHandler).Pointer(), msg("should have set error handler")) } } }
func (s *TrackerTestSuite) SetupTest() { var err error s.Request, err = acomm.NewRequest("foobar", s.RespServer.URL, nil, nil, nil) s.Require().NoError(err, "request should be valid") streamAddr, _ := url.ParseRequestURI(s.StreamServer.URL) s.Tracker, err = acomm.NewTracker("", streamAddr, 0) s.Require().NoError(err, "failed to create new Tracker") s.Require().NotNil(s.Tracker, "failed to create new Tracker") }
func (s *RequestTestSuite) TestHandleResponse() { sh, eh, handled := generateHandlers() respErr := errors.New("foobar") tests := []struct { description string sh acomm.ResponseHandler eh acomm.ResponseHandler respResult interface{} respErr error }{ {"sh handler, err resp", sh, nil, nil, respErr}, {"sh handler, success resp", sh, nil, struct{}{}, nil}, {"eh handler, err resp", nil, eh, nil, respErr}, {"eh handler, success resp", nil, eh, struct{}{}, nil}, {"both handlers, err resp", sh, eh, nil, respErr}, {"both handlers, success resp", sh, eh, struct{}{}, nil}, } for _, test := range tests { handled["success"] = 0 handled["error"] = 0 msg := testMsgFunc(test.description) req, err := acomm.NewRequest("foobar", "unix://foo", struct{}{}, test.sh, test.eh) if !s.NoError(err, msg("should not fail to build req")) { continue } resp, err := acomm.NewResponse(req, test.respResult, nil, test.respErr) if !s.NoError(err, msg("should not fail to build resp")) { continue } req.HandleResponse(resp) if test.respErr != nil { s.Equal(0, handled["success"], msg("should not have called success handler")) if test.eh != nil { s.Equal(1, handled["error"], msg("should have called error handler")) } else { s.Equal(0, handled["error"], msg("should not have called error handler")) } } else { if test.sh != nil { s.Equal(1, handled["success"], msg("should have called success handler")) } else { s.Equal(0, handled["success"], msg("should not have called success handler")) } s.Equal(0, handled["error"], msg("should not have called error handler")) } } }
func makeRequest(coordinator, taskName, responseAddr string, taskArgs map[string]interface{}) error { coordinatorURL, err := url.ParseRequestURI(coordinator) if err != nil { return errors.New("invalid coordinator url") } responseHook := fmt.Sprintf("http://%s/", responseAddr) req, err := acomm.NewRequest(taskName, responseHook, taskArgs, nil, nil) if err != nil { return err } return acomm.Send(coordinatorURL, req) }
func (s *ResponseTestSuite) TestNewResponse() { result := map[string]string{ "foo": "bar", } request, _ := acomm.NewRequest("foobar", "unix://foo", nil, nil, nil) respErr := errors.New("foobar") tests := []struct { description string request *acomm.Request result interface{} err error expectedErr bool }{ {"missing request", nil, result, nil, true}, {"missing result and error", request, nil, nil, false}, {"result and error", request, result, respErr, true}, {"result only", request, result, nil, false}, {"error only", request, nil, respErr, false}, } for _, test := range tests { msg := testMsgFunc(test.description) resp, err := acomm.NewResponse(test.request, test.result, nil, test.err) if test.expectedErr { s.Error(err, msg("should have failed")) s.Nil(resp, msg("should not have returned a response")) } else { if !s.NoError(err, msg("should have succeeded")) { s.T().Log(msg(err.Error())) continue } if !s.NotNil(resp, msg("should have returned a response")) { continue } s.Equal(test.request.ID, resp.ID, msg("should have set an ID")) var result map[string]string s.NoError(resp.UnmarshalResult(&result)) if test.result == nil { s.Nil(result, msg("should have nil result")) } else { s.Equal(test.result, result, msg("should have set the result")) } s.Equal(test.err, resp.Error, msg("should have set the error")) } } }
func (s *TrackerTestSuite) TestProxyUnix() { unixReq, err := s.Tracker.ProxyUnix(s.Request, 0) s.Error(err, "should fail to proxy when tracker is not listening") s.Nil(unixReq, "should not return a request") if !s.NoError(s.Tracker.Start(), "listner should start") { return } unixReq, err = s.Tracker.ProxyUnix(s.Request, 0) s.NoError(err, "should not fail proxying when tracker is listening") s.NotNil(unixReq, "should return a request") s.Equal(s.Request.ID, unixReq.ID, "new request should share ID with original") s.Equal("unix", unixReq.ResponseHook.Scheme, "new request should have a unix response hook") s.Equal(1, s.Tracker.NumRequests(), "should have tracked the new request") resp, err := acomm.NewResponse(unixReq, struct{}{}, nil, nil) if !s.NoError(err, "new response should not error") { return } if !s.NoError(acomm.Send(unixReq.ResponseHook, resp), "response send should not error") { return } lastResp := s.NextResp() if !s.NotNil(lastResp, "response should have been proxied to original http response hook") { return } s.Equal(resp.ID, lastResp.ID, "response should have been proxied to original http response hook") s.Equal(0, s.Tracker.NumRequests(), "should have removed the request from tracking") // Should not proxy a request already using unix response hook origUnixReq, err := acomm.NewRequest("foobar", "unix://foo", struct{}{}, nil, nil) if !s.NoError(err, "new request shoudl not error") { return } unixReq, err = s.Tracker.ProxyUnix(origUnixReq, 0) s.NoError(err, "should not error with unix response hook") s.Equal(origUnixReq, unixReq, "should not proxy unix response hook") s.Equal(0, s.Tracker.NumRequests(), "should not response an unproxied request") }
// SystemStatus is a task handler to retrieve info look up and return system // information. It depends on and makes requests for several other tasks. func (s *Simple) SystemStatus(req *acomm.Request) (interface{}, *url.URL, error) { var args SystemStatusArgs if err := req.UnmarshalArgs(&args); err != nil { return nil, nil, err } if args.GuestID == "" { return nil, nil, errors.New("missing guest_id") } // Prepare multiple requests multiRequest := acomm.NewMultiRequest(s.tracker, 0) cpuReq, err := acomm.NewRequest("CPUInfo", s.tracker.URL().String(), &CPUInfoArgs{GuestID: args.GuestID}, nil, nil) if err != nil { return nil, nil, err } diskReq, err := acomm.NewRequest("DiskInfo", s.tracker.URL().String(), &DiskInfoArgs{GuestID: args.GuestID}, nil, nil) if err != nil { return nil, nil, err } requests := map[string]*acomm.Request{ "CPUInfo": cpuReq, "DiskInfo": diskReq, } for name, req := range requests { if err := multiRequest.AddRequest(name, req); err != nil { continue } if err := acomm.Send(s.config.CoordinatorURL(), req); err != nil { multiRequest.RemoveRequest(req) continue } } // Wait for the results responses := multiRequest.Responses() result := &SystemStatusResult{} if resp, ok := responses["CPUInfo"]; ok { if err := resp.UnmarshalResult(&(result.CPUs)); err != nil { log.WithFields(log.Fields{ "name": "CPUInfo", "resp": resp, "error": err, }).Error("failed to unarshal result") } } if resp, ok := responses["DiskInfo"]; ok { if err := resp.UnmarshalResult(&(result.Disks)); err != nil { log.WithFields(log.Fields{ "name": "DiskInfo", "resp": resp, "error": err, }).Error("failed to unarshal result") } } return result, nil, nil }
func (s *ServerSuite) TestReqRespHandle() { // Start if !s.NoError(s.server.Start(), "failed to start server") { return } time.Sleep(time.Second) // Stop defer s.server.Stop() // Set up handlers result := make(chan *params, 10) // Task handler taskName := "foobar" taskListener := s.createTaskListener(taskName, result) if taskListener == nil { return } defer taskListener.Stop(0) // Response handlers responseServer, responseListener := s.createResponseHandlers(result) if responseServer != nil { defer responseServer.Close() } if responseListener != nil { defer responseListener.Stop(0) } if responseServer == nil || responseListener == nil { return } // Coordinator URLs internalURL, _ := url.ParseRequestURI("unix://" + filepath.Join( s.config.SocketDir(), "coordinator", s.config.ServiceName()+".sock"), ) externalURL, _ := url.ParseRequestURI(fmt.Sprintf( "http://localhost:%v", s.configData.ExternalPort), ) // Test cases tests := []struct { description string taskName string internal bool params *params expectFailed bool }{ {"valid http", taskName, false, ¶ms{uuid.New()}, false}, {"valid unix", taskName, true, ¶ms{uuid.New()}, false}, {"bad task http", "asdf", false, ¶ms{uuid.New()}, true}, {"bad task unix", "asdf", true, ¶ms{uuid.New()}, true}, } for _, test := range tests { msg := testMsgFunc(test.description) hookURL := responseServer.URL coordinatorURL := externalURL if test.internal { hookURL = responseListener.URL().String() coordinatorURL = internalURL } req, _ := acomm.NewRequest(test.taskName, hookURL, test.params, nil, nil) if err := acomm.Send(coordinatorURL, req); err != nil { result <- nil } respData := <-result if test.expectFailed { s.Nil(respData, msg("should have failed")) } else { s.Equal(test.params, respData, msg("should have gotten the correct response data")) } drainChan(result) } }