| // Copyright 2014 Google Inc. All rights reserved. | |
| // Use of this source code is governed by the Apache 2.0 | |
| // license that can be found in the LICENSE file. | |
| package taskqueue | |
| import ( | |
| "errors" | |
| "fmt" | |
| "net/http" | |
| "reflect" | |
| "testing" | |
| "time" | |
| "google.golang.org/appengine" | |
| "google.golang.org/appengine/internal" | |
| "google.golang.org/appengine/internal/aetesting" | |
| pb "google.golang.org/appengine/internal/taskqueue" | |
| ) | |
| func TestAddErrors(t *testing.T) { | |
| var tests = []struct { | |
| err, want error | |
| sameErr bool // if true, should return err exactly | |
| }{ | |
| { | |
| err: &internal.APIError{ | |
| Service: "taskqueue", | |
| Code: int32(pb.TaskQueueServiceError_TASK_ALREADY_EXISTS), | |
| }, | |
| want: ErrTaskAlreadyAdded, | |
| }, | |
| { | |
| err: &internal.APIError{ | |
| Service: "taskqueue", | |
| Code: int32(pb.TaskQueueServiceError_TOMBSTONED_TASK), | |
| }, | |
| want: ErrTaskAlreadyAdded, | |
| }, | |
| { | |
| err: &internal.APIError{ | |
| Service: "taskqueue", | |
| Code: int32(pb.TaskQueueServiceError_UNKNOWN_QUEUE), | |
| }, | |
| want: errors.New("not used"), | |
| sameErr: true, | |
| }, | |
| } | |
| for _, tc := range tests { | |
| c := aetesting.FakeSingleContext(t, "taskqueue", "Add", func(req *pb.TaskQueueAddRequest, res *pb.TaskQueueAddResponse) error { | |
| // don't fill in any of the response | |
| return tc.err | |
| }) | |
| task := &Task{Path: "/worker", Method: "PULL"} | |
| _, err := Add(c, task, "a-queue") | |
| want := tc.want | |
| if tc.sameErr { | |
| want = tc.err | |
| } | |
| if err != want { | |
| t.Errorf("Add with tc.err = %v, got %#v, want = %#v", tc.err, err, want) | |
| } | |
| } | |
| } | |
| func TestAddMulti(t *testing.T) { | |
| c := aetesting.FakeSingleContext(t, "taskqueue", "BulkAdd", func(req *pb.TaskQueueBulkAddRequest, res *pb.TaskQueueBulkAddResponse) error { | |
| res.Taskresult = []*pb.TaskQueueBulkAddResponse_TaskResult{ | |
| { | |
| Result: pb.TaskQueueServiceError_OK.Enum(), | |
| }, | |
| { | |
| Result: pb.TaskQueueServiceError_TASK_ALREADY_EXISTS.Enum(), | |
| }, | |
| { | |
| Result: pb.TaskQueueServiceError_TOMBSTONED_TASK.Enum(), | |
| }, | |
| { | |
| Result: pb.TaskQueueServiceError_INTERNAL_ERROR.Enum(), | |
| }, | |
| } | |
| return nil | |
| }) | |
| tasks := []*Task{ | |
| {Path: "/worker", Method: "PULL"}, | |
| {Path: "/worker", Method: "PULL"}, | |
| {Path: "/worker", Method: "PULL"}, | |
| {Path: "/worker", Method: "PULL"}, | |
| } | |
| r, err := AddMulti(c, tasks, "a-queue") | |
| if len(r) != len(tasks) { | |
| t.Fatalf("AddMulti returned %d tasks, want %d", len(r), len(tasks)) | |
| } | |
| want := appengine.MultiError{ | |
| nil, | |
| ErrTaskAlreadyAdded, | |
| ErrTaskAlreadyAdded, | |
| &internal.APIError{ | |
| Service: "taskqueue", | |
| Code: int32(pb.TaskQueueServiceError_INTERNAL_ERROR), | |
| }, | |
| } | |
| if !reflect.DeepEqual(err, want) { | |
| t.Errorf("AddMulti got %v, wanted %v", err, want) | |
| } | |
| } | |
| func TestAddWithEmptyPath(t *testing.T) { | |
| c := aetesting.FakeSingleContext(t, "taskqueue", "Add", func(req *pb.TaskQueueAddRequest, res *pb.TaskQueueAddResponse) error { | |
| if got, want := string(req.Url), "/_ah/queue/a-queue"; got != want { | |
| return fmt.Errorf("req.Url = %q; want %q", got, want) | |
| } | |
| return nil | |
| }) | |
| if _, err := Add(c, &Task{}, "a-queue"); err != nil { | |
| t.Fatalf("Add: %v", err) | |
| } | |
| } | |
| func TestParseRequestHeaders(t *testing.T) { | |
| tests := []struct { | |
| Header http.Header | |
| Want RequestHeaders | |
| }{ | |
| { | |
| Header: map[string][]string{ | |
| "X-Appengine-Queuename": []string{"foo"}, | |
| "X-Appengine-Taskname": []string{"bar"}, | |
| "X-Appengine-Taskretrycount": []string{"4294967297"}, // 2^32 + 1 | |
| "X-Appengine-Taskexecutioncount": []string{"4294967298"}, // 2^32 + 2 | |
| "X-Appengine-Tasketa": []string{"1500000000"}, | |
| "X-Appengine-Taskpreviousresponse": []string{"404"}, | |
| "X-Appengine-Taskretryreason": []string{"baz"}, | |
| "X-Appengine-Failfast": []string{"yes"}, | |
| }, | |
| Want: RequestHeaders{ | |
| QueueName: "foo", | |
| TaskName: "bar", | |
| TaskRetryCount: 4294967297, | |
| TaskExecutionCount: 4294967298, | |
| TaskETA: time.Date(2017, time.July, 14, 2, 40, 0, 0, time.UTC), | |
| TaskPreviousResponse: 404, | |
| TaskRetryReason: "baz", | |
| FailFast: true, | |
| }, | |
| }, | |
| { | |
| Header: map[string][]string{}, | |
| Want: RequestHeaders{ | |
| QueueName: "", | |
| TaskName: "", | |
| TaskRetryCount: 0, | |
| TaskExecutionCount: 0, | |
| TaskETA: time.Time{}, | |
| TaskPreviousResponse: 0, | |
| TaskRetryReason: "", | |
| FailFast: false, | |
| }, | |
| }, | |
| } | |
| for idx, test := range tests { | |
| got := *ParseRequestHeaders(test.Header) | |
| if got.TaskETA.UnixNano() != test.Want.TaskETA.UnixNano() { | |
| t.Errorf("%d. ParseRequestHeaders got TaskETA %v, wanted %v", idx, got.TaskETA, test.Want.TaskETA) | |
| } | |
| got.TaskETA = time.Time{} | |
| test.Want.TaskETA = time.Time{} | |
| if !reflect.DeepEqual(got, test.Want) { | |
| t.Errorf("%d. ParseRequestHeaders got %v, wanted %v", idx, got, test.Want) | |
| } | |
| } | |
| } |