Revert "Copy codes and status from grpc project"
This reverts commit f02233564f
.
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
923a8f1f17
commit
d4834b09f5
@ -23,9 +23,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/containerd/ttrpc/status"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -23,9 +23,9 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/containerd/ttrpc/status"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadWriteMessage(t *testing.T) {
|
func TestReadWriteMessage(t *testing.T) {
|
||||||
|
@ -26,11 +26,11 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/containerd/ttrpc/status"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrClosed is returned by client methods when the underlying connection is
|
// ErrClosed is returned by client methods when the underlying connection is
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2017 gRPC authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package codes
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
func (c Code) String() string {
|
|
||||||
switch c {
|
|
||||||
case OK:
|
|
||||||
return "OK"
|
|
||||||
case Canceled:
|
|
||||||
return "Canceled"
|
|
||||||
case Unknown:
|
|
||||||
return "Unknown"
|
|
||||||
case InvalidArgument:
|
|
||||||
return "InvalidArgument"
|
|
||||||
case DeadlineExceeded:
|
|
||||||
return "DeadlineExceeded"
|
|
||||||
case NotFound:
|
|
||||||
return "NotFound"
|
|
||||||
case AlreadyExists:
|
|
||||||
return "AlreadyExists"
|
|
||||||
case PermissionDenied:
|
|
||||||
return "PermissionDenied"
|
|
||||||
case ResourceExhausted:
|
|
||||||
return "ResourceExhausted"
|
|
||||||
case FailedPrecondition:
|
|
||||||
return "FailedPrecondition"
|
|
||||||
case Aborted:
|
|
||||||
return "Aborted"
|
|
||||||
case OutOfRange:
|
|
||||||
return "OutOfRange"
|
|
||||||
case Unimplemented:
|
|
||||||
return "Unimplemented"
|
|
||||||
case Internal:
|
|
||||||
return "Internal"
|
|
||||||
case Unavailable:
|
|
||||||
return "Unavailable"
|
|
||||||
case DataLoss:
|
|
||||||
return "DataLoss"
|
|
||||||
case Unauthenticated:
|
|
||||||
return "Unauthenticated"
|
|
||||||
default:
|
|
||||||
return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
|
|
||||||
}
|
|
||||||
}
|
|
214
codes/codes.go
214
codes/codes.go
@ -1,214 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2014 gRPC authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package codes defines the canonical error codes used by gRPC. It is
|
|
||||||
// consistent across various languages.
|
|
||||||
package codes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Code is an unsigned 32-bit error code as defined in the gRPC spec.
|
|
||||||
type Code uint32
|
|
||||||
|
|
||||||
const (
|
|
||||||
// OK is returned on success.
|
|
||||||
OK Code = 0
|
|
||||||
|
|
||||||
// Canceled indicates the operation was canceled (typically by the caller).
|
|
||||||
Canceled Code = 1
|
|
||||||
|
|
||||||
// Unknown error. An example of where this error may be returned is
|
|
||||||
// if a Status value received from another address space belongs to
|
|
||||||
// an error-space that is not known in this address space. Also
|
|
||||||
// errors raised by APIs that do not return enough error information
|
|
||||||
// may be converted to this error.
|
|
||||||
Unknown Code = 2
|
|
||||||
|
|
||||||
// InvalidArgument indicates client specified an invalid argument.
|
|
||||||
// Note that this differs from FailedPrecondition. It indicates arguments
|
|
||||||
// that are problematic regardless of the state of the system
|
|
||||||
// (e.g., a malformed file name).
|
|
||||||
InvalidArgument Code = 3
|
|
||||||
|
|
||||||
// DeadlineExceeded means operation expired before completion.
|
|
||||||
// For operations that change the state of the system, this error may be
|
|
||||||
// returned even if the operation has completed successfully. For
|
|
||||||
// example, a successful response from a server could have been delayed
|
|
||||||
// long enough for the deadline to expire.
|
|
||||||
DeadlineExceeded Code = 4
|
|
||||||
|
|
||||||
// NotFound means some requested entity (e.g., file or directory) was
|
|
||||||
// not found.
|
|
||||||
NotFound Code = 5
|
|
||||||
|
|
||||||
// AlreadyExists means an attempt to create an entity failed because one
|
|
||||||
// already exists.
|
|
||||||
AlreadyExists Code = 6
|
|
||||||
|
|
||||||
// PermissionDenied indicates the caller does not have permission to
|
|
||||||
// execute the specified operation. It must not be used for rejections
|
|
||||||
// caused by exhausting some resource (use ResourceExhausted
|
|
||||||
// instead for those errors). It must not be
|
|
||||||
// used if the caller cannot be identified (use Unauthenticated
|
|
||||||
// instead for those errors).
|
|
||||||
PermissionDenied Code = 7
|
|
||||||
|
|
||||||
// ResourceExhausted indicates some resource has been exhausted, perhaps
|
|
||||||
// a per-user quota, or perhaps the entire file system is out of space.
|
|
||||||
ResourceExhausted Code = 8
|
|
||||||
|
|
||||||
// FailedPrecondition indicates operation was rejected because the
|
|
||||||
// system is not in a state required for the operation's execution.
|
|
||||||
// For example, directory to be deleted may be non-empty, an rmdir
|
|
||||||
// operation is applied to a non-directory, etc.
|
|
||||||
//
|
|
||||||
// A litmus test that may help a service implementor in deciding
|
|
||||||
// between FailedPrecondition, Aborted, and Unavailable:
|
|
||||||
// (a) Use Unavailable if the client can retry just the failing call.
|
|
||||||
// (b) Use Aborted if the client should retry at a higher-level
|
|
||||||
// (e.g., restarting a read-modify-write sequence).
|
|
||||||
// (c) Use FailedPrecondition if the client should not retry until
|
|
||||||
// the system state has been explicitly fixed. E.g., if an "rmdir"
|
|
||||||
// fails because the directory is non-empty, FailedPrecondition
|
|
||||||
// should be returned since the client should not retry unless
|
|
||||||
// they have first fixed up the directory by deleting files from it.
|
|
||||||
// (d) Use FailedPrecondition if the client performs conditional
|
|
||||||
// REST Get/Update/Delete on a resource and the resource on the
|
|
||||||
// server does not match the condition. E.g., conflicting
|
|
||||||
// read-modify-write on the same resource.
|
|
||||||
FailedPrecondition Code = 9
|
|
||||||
|
|
||||||
// Aborted indicates the operation was aborted, typically due to a
|
|
||||||
// concurrency issue like sequencer check failures, transaction aborts,
|
|
||||||
// etc.
|
|
||||||
//
|
|
||||||
// See litmus test above for deciding between FailedPrecondition,
|
|
||||||
// Aborted, and Unavailable.
|
|
||||||
Aborted Code = 10
|
|
||||||
|
|
||||||
// OutOfRange means operation was attempted past the valid range.
|
|
||||||
// E.g., seeking or reading past end of file.
|
|
||||||
//
|
|
||||||
// Unlike InvalidArgument, this error indicates a problem that may
|
|
||||||
// be fixed if the system state changes. For example, a 32-bit file
|
|
||||||
// system will generate InvalidArgument if asked to read at an
|
|
||||||
// offset that is not in the range [0,2^32-1], but it will generate
|
|
||||||
// OutOfRange if asked to read from an offset past the current
|
|
||||||
// file size.
|
|
||||||
//
|
|
||||||
// There is a fair bit of overlap between FailedPrecondition and
|
|
||||||
// OutOfRange. We recommend using OutOfRange (the more specific
|
|
||||||
// error) when it applies so that callers who are iterating through
|
|
||||||
// a space can easily look for an OutOfRange error to detect when
|
|
||||||
// they are done.
|
|
||||||
OutOfRange Code = 11
|
|
||||||
|
|
||||||
// Unimplemented indicates operation is not implemented or not
|
|
||||||
// supported/enabled in this service.
|
|
||||||
Unimplemented Code = 12
|
|
||||||
|
|
||||||
// Internal errors. Means some invariants expected by underlying
|
|
||||||
// system has been broken. If you see one of these errors,
|
|
||||||
// something is very broken.
|
|
||||||
Internal Code = 13
|
|
||||||
|
|
||||||
// Unavailable indicates the service is currently unavailable.
|
|
||||||
// This is a most likely a transient condition and may be corrected
|
|
||||||
// by retrying with a backoff. Note that it is not always safe to retry
|
|
||||||
// non-idempotent operations.
|
|
||||||
//
|
|
||||||
// See litmus test above for deciding between FailedPrecondition,
|
|
||||||
// Aborted, and Unavailable.
|
|
||||||
Unavailable Code = 14
|
|
||||||
|
|
||||||
// DataLoss indicates unrecoverable data loss or corruption.
|
|
||||||
DataLoss Code = 15
|
|
||||||
|
|
||||||
// Unauthenticated indicates the request does not have valid
|
|
||||||
// authentication credentials for the operation.
|
|
||||||
Unauthenticated Code = 16
|
|
||||||
|
|
||||||
_maxCode = 17
|
|
||||||
)
|
|
||||||
|
|
||||||
var strToCode = map[string]Code{
|
|
||||||
`"OK"`: OK,
|
|
||||||
`"CANCELLED"`:/* [sic] */ Canceled,
|
|
||||||
`"UNKNOWN"`: Unknown,
|
|
||||||
`"INVALID_ARGUMENT"`: InvalidArgument,
|
|
||||||
`"DEADLINE_EXCEEDED"`: DeadlineExceeded,
|
|
||||||
`"NOT_FOUND"`: NotFound,
|
|
||||||
`"ALREADY_EXISTS"`: AlreadyExists,
|
|
||||||
`"PERMISSION_DENIED"`: PermissionDenied,
|
|
||||||
`"RESOURCE_EXHAUSTED"`: ResourceExhausted,
|
|
||||||
`"FAILED_PRECONDITION"`: FailedPrecondition,
|
|
||||||
`"ABORTED"`: Aborted,
|
|
||||||
`"OUT_OF_RANGE"`: OutOfRange,
|
|
||||||
`"UNIMPLEMENTED"`: Unimplemented,
|
|
||||||
`"INTERNAL"`: Internal,
|
|
||||||
`"UNAVAILABLE"`: Unavailable,
|
|
||||||
`"DATA_LOSS"`: DataLoss,
|
|
||||||
`"UNAUTHENTICATED"`: Unauthenticated,
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals b into the Code.
|
|
||||||
func (c *Code) UnmarshalJSON(b []byte) error {
|
|
||||||
// From json.Unmarshaler: By convention, to approximate the behavior of
|
|
||||||
// Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
|
|
||||||
// a no-op.
|
|
||||||
if string(b) == "null" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if c == nil {
|
|
||||||
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
|
|
||||||
if ci >= _maxCode {
|
|
||||||
return fmt.Errorf("invalid code: %q", ci)
|
|
||||||
}
|
|
||||||
|
|
||||||
*c = Code(ci)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if jc, ok := strToCode[string(b)]; ok {
|
|
||||||
*c = jc
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("invalid code: %q", string(b))
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2017 gRPC authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package codes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
cpb "google.golang.org/genproto/googleapis/rpc/code"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUnmarshalJSON(t *testing.T) {
|
|
||||||
for s, v := range cpb.Code_value {
|
|
||||||
want := Code(v)
|
|
||||||
var got Code
|
|
||||||
if err := got.UnmarshalJSON([]byte(`"` + s + `"`)); err != nil || got != want {
|
|
||||||
t.Errorf("got.UnmarshalJSON(%q) = %v; want <nil>. got=%v; want %v", s, err, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJSONUnmarshal(t *testing.T) {
|
|
||||||
var got []Code
|
|
||||||
want := []Code{OK, NotFound, Internal, Canceled}
|
|
||||||
in := `["OK", "NOT_FOUND", "INTERNAL", "CANCELLED"]`
|
|
||||||
err := json.Unmarshal([]byte(in), &got)
|
|
||||||
if err != nil || !reflect.DeepEqual(got, want) {
|
|
||||||
t.Fatalf("json.Unmarshal(%q, &got) = %v; want <nil>. got=%v; want %v", in, err, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalJSON_NilReceiver(t *testing.T) {
|
|
||||||
var got *Code
|
|
||||||
in := OK.String()
|
|
||||||
if err := got.UnmarshalJSON([]byte(in)); err == nil {
|
|
||||||
t.Errorf("got.UnmarshalJSON(%q) = nil; want <non-nil>. got=%v", in, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalJSON_UnknownInput(t *testing.T) {
|
|
||||||
var got Code
|
|
||||||
for _, in := range [][]byte{[]byte(""), []byte("xxx"), []byte("Code(17)"), nil} {
|
|
||||||
if err := got.UnmarshalJSON([]byte(in)); err == nil {
|
|
||||||
t.Errorf("got.UnmarshalJSON(%q) = nil; want <non-nil>. got=%v", in, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalJSON_MarshalUnmarshal(t *testing.T) {
|
|
||||||
for i := 0; i < _maxCode; i++ {
|
|
||||||
var cUnMarshaled Code
|
|
||||||
c := Code(i)
|
|
||||||
|
|
||||||
cJSON, err := json.Marshal(c)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("marshalling %q failed: %v", c, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(cJSON, &cUnMarshaled); err != nil {
|
|
||||||
t.Errorf("unmarshalling code failed: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c != cUnMarshaled {
|
|
||||||
t.Errorf("code is %q after marshalling/unmarshalling, expected %q", cUnMarshaled, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
20
codes/doc.go
20
codes/doc.go
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This package has been copied over from the v1.23.1 release of go grpc
|
|
||||||
// There are stability issues with point releases of grpc and ttrpc
|
|
||||||
// only uses the codes and status package from grpc
|
|
||||||
package codes
|
|
1
go.mod
1
go.mod
@ -4,7 +4,6 @@ go 1.12
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gogo/protobuf v1.2.1
|
github.com/gogo/protobuf v1.2.1
|
||||||
github.com/golang/protobuf v1.3.1
|
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1
|
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
|
3
go.sum
3
go.sum
@ -5,7 +5,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@ -35,7 +34,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -46,7 +44,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU=
|
golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU=
|
||||||
golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -25,10 +25,10 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/containerd/ttrpc/status"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -26,11 +26,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/containerd/ttrpc/status"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
const serviceName = "testService"
|
const serviceName = "testService"
|
||||||
|
@ -23,10 +23,10 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/containerd/ttrpc/status"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Method func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error)
|
type Method func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error)
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This package has been copied over from the v1.23.1 release of go grpc
|
|
||||||
// There are stability issues with point releases of grpc and ttrpc
|
|
||||||
// only uses the codes and status package from grpc
|
|
||||||
package status
|
|
237
status/status.go
237
status/status.go
@ -1,237 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2017 gRPC authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package status implements errors returned by gRPC. These errors are
|
|
||||||
// serialized and transmitted on the wire between server and client, and allow
|
|
||||||
// for additional data to be transmitted via the Details field in the status
|
|
||||||
// proto. gRPC service handlers should return an error created by this
|
|
||||||
// package, and gRPC clients should expect a corresponding error to be
|
|
||||||
// returned from the RPC call.
|
|
||||||
//
|
|
||||||
// This package upholds the invariants that a non-nil error may not
|
|
||||||
// contain an OK code, and an OK code must result in a nil error.
|
|
||||||
package status
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/golang/protobuf/ptypes"
|
|
||||||
spb "google.golang.org/genproto/googleapis/rpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// statusError is an alias of a status proto. It implements error and Status,
|
|
||||||
// and a nil statusError should never be returned by this package.
|
|
||||||
type statusError spb.Status
|
|
||||||
|
|
||||||
func (se *statusError) Error() string {
|
|
||||||
p := (*spb.Status)(se)
|
|
||||||
return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (se *statusError) GRPCStatus() *Status {
|
|
||||||
return &Status{s: (*spb.Status)(se)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is implements future error.Is functionality.
|
|
||||||
// A statusError is equivalent if the code and message are identical.
|
|
||||||
func (se *statusError) Is(target error) bool {
|
|
||||||
tse, ok := target.(*statusError)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return proto.Equal((*spb.Status)(se), (*spb.Status)(tse))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status represents an RPC status code, message, and details. It is immutable
|
|
||||||
// and should be created with New, Newf, or FromProto.
|
|
||||||
type Status struct {
|
|
||||||
s *spb.Status
|
|
||||||
}
|
|
||||||
|
|
||||||
// Code returns the status code contained in s.
|
|
||||||
func (s *Status) Code() codes.Code {
|
|
||||||
if s == nil || s.s == nil {
|
|
||||||
return codes.OK
|
|
||||||
}
|
|
||||||
return codes.Code(s.s.Code)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message returns the message contained in s.
|
|
||||||
func (s *Status) Message() string {
|
|
||||||
if s == nil || s.s == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return s.s.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
// Proto returns s's status as an spb.Status proto message.
|
|
||||||
func (s *Status) Proto() *spb.Status {
|
|
||||||
if s == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return proto.Clone(s.s).(*spb.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Err returns an immutable error representing s; returns nil if s.Code() is
|
|
||||||
// OK.
|
|
||||||
func (s *Status) Err() error {
|
|
||||||
if s.Code() == codes.OK {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return (*statusError)(s.s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a Status representing c and msg.
|
|
||||||
func New(c codes.Code, msg string) *Status {
|
|
||||||
return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Newf returns New(c, fmt.Sprintf(format, a...)).
|
|
||||||
func Newf(c codes.Code, format string, a ...interface{}) *Status {
|
|
||||||
return New(c, fmt.Sprintf(format, a...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns an error representing c and msg. If c is OK, returns nil.
|
|
||||||
func Error(c codes.Code, msg string) error {
|
|
||||||
return New(c, msg).Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf returns Error(c, fmt.Sprintf(format, a...)).
|
|
||||||
func Errorf(c codes.Code, format string, a ...interface{}) error {
|
|
||||||
return Error(c, fmt.Sprintf(format, a...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorProto returns an error representing s. If s.Code is OK, returns nil.
|
|
||||||
func ErrorProto(s *spb.Status) error {
|
|
||||||
return FromProto(s).Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromProto returns a Status representing s.
|
|
||||||
func FromProto(s *spb.Status) *Status {
|
|
||||||
return &Status{s: proto.Clone(s).(*spb.Status)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromError returns a Status representing err if it was produced from this
|
|
||||||
// package or has a method `GRPCStatus() *Status`. Otherwise, ok is false and a
|
|
||||||
// Status is returned with codes.Unknown and the original error message.
|
|
||||||
func FromError(err error) (s *Status, ok bool) {
|
|
||||||
if err == nil {
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
if se, ok := err.(interface {
|
|
||||||
GRPCStatus() *Status
|
|
||||||
}); ok {
|
|
||||||
return se.GRPCStatus(), true
|
|
||||||
}
|
|
||||||
return New(codes.Unknown, err.Error()), false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert is a convenience function which removes the need to handle the
|
|
||||||
// boolean return value from FromError.
|
|
||||||
func Convert(err error) *Status {
|
|
||||||
s, _ := FromError(err)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDetails returns a new status with the provided details messages appended to the status.
|
|
||||||
// If any errors are encountered, it returns nil and the first error encountered.
|
|
||||||
func (s *Status) WithDetails(details ...proto.Message) (*Status, error) {
|
|
||||||
if s.Code() == codes.OK {
|
|
||||||
return nil, errors.New("no error details for status with code OK")
|
|
||||||
}
|
|
||||||
// s.Code() != OK implies that s.Proto() != nil.
|
|
||||||
p := s.Proto()
|
|
||||||
for _, detail := range details {
|
|
||||||
any, err := ptypes.MarshalAny(detail)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.Details = append(p.Details, any)
|
|
||||||
}
|
|
||||||
return &Status{s: p}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Details returns a slice of details messages attached to the status.
|
|
||||||
// If a detail cannot be decoded, the error is returned in place of the detail.
|
|
||||||
func (s *Status) Details() []interface{} {
|
|
||||||
if s == nil || s.s == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
details := make([]interface{}, 0, len(s.s.Details))
|
|
||||||
for _, any := range s.s.Details {
|
|
||||||
detail := &ptypes.DynamicAny{}
|
|
||||||
if err := ptypes.UnmarshalAny(any, detail); err != nil {
|
|
||||||
details = append(details, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
details = append(details, detail.Message)
|
|
||||||
}
|
|
||||||
return details
|
|
||||||
}
|
|
||||||
|
|
||||||
// Code returns the Code of the error if it is a Status error, codes.OK if err
|
|
||||||
// is nil, or codes.Unknown otherwise.
|
|
||||||
func Code(err error) codes.Code {
|
|
||||||
// Don't use FromError to avoid allocation of OK status.
|
|
||||||
if err == nil {
|
|
||||||
return codes.OK
|
|
||||||
}
|
|
||||||
if se, ok := err.(interface {
|
|
||||||
GRPCStatus() *Status
|
|
||||||
}); ok {
|
|
||||||
return se.GRPCStatus().Code()
|
|
||||||
}
|
|
||||||
return codes.Unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromContextError converts a context error into a Status. It returns a
|
|
||||||
// Status with codes.OK if err is nil, or a Status with codes.Unknown if err is
|
|
||||||
// non-nil and not a context error.
|
|
||||||
func FromContextError(err error) *Status {
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
return nil
|
|
||||||
case context.DeadlineExceeded:
|
|
||||||
return New(codes.DeadlineExceeded, err.Error())
|
|
||||||
case context.Canceled:
|
|
||||||
return New(codes.Canceled, err.Error())
|
|
||||||
default:
|
|
||||||
return New(codes.Unknown, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2019 gRPC authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package status_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/containerd/ttrpc/status"
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"google.golang.org/grpc/test/grpc_testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func errWithDetails(t *testing.T, s *status.Status, details ...proto.Message) error {
|
|
||||||
t.Helper()
|
|
||||||
res, err := s.WithDetails(details...)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("(%v).WithDetails(%v) = %v, %v; want _, <nil>", s, details, res, err)
|
|
||||||
}
|
|
||||||
return res.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorIs(t *testing.T) {
|
|
||||||
// Test errors.
|
|
||||||
testErr := status.Error(codes.Internal, "internal server error")
|
|
||||||
testErrWithDetails := errWithDetails(t, status.New(codes.Internal, "internal server error"), &grpc_testing.Empty{})
|
|
||||||
|
|
||||||
// Test cases.
|
|
||||||
testCases := []struct {
|
|
||||||
err1, err2 error
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{err1: testErr, err2: nil, want: false},
|
|
||||||
{err1: testErr, err2: status.Error(codes.Internal, "internal server error"), want: true},
|
|
||||||
{err1: testErr, err2: status.Error(codes.Internal, "internal error"), want: false},
|
|
||||||
{err1: testErr, err2: status.Error(codes.Unknown, "internal server error"), want: false},
|
|
||||||
{err1: testErr, err2: errors.New("non-grpc error"), want: false},
|
|
||||||
{err1: testErrWithDetails, err2: status.Error(codes.Internal, "internal server error"), want: false},
|
|
||||||
{err1: testErrWithDetails, err2: errWithDetails(t, status.New(codes.Internal, "internal server error"), &grpc_testing.Empty{}), want: true},
|
|
||||||
{err1: testErrWithDetails, err2: errWithDetails(t, status.New(codes.Internal, "internal server error"), &grpc_testing.Empty{}, &grpc_testing.Empty{}), want: false},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
isError, ok := tc.err1.(interface{ Is(target error) bool })
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("(%v) does not implement is", tc.err1)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
is := isError.Is(tc.err2)
|
|
||||||
if is != tc.want {
|
|
||||||
t.Errorf("(%v).Is(%v) = %t; want %t", tc.err1, tc.err2, is, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,378 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2017 gRPC authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package status
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/containerd/ttrpc/codes"
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/golang/protobuf/ptypes"
|
|
||||||
apb "github.com/golang/protobuf/ptypes/any"
|
|
||||||
dpb "github.com/golang/protobuf/ptypes/duration"
|
|
||||||
cpb "google.golang.org/genproto/googleapis/rpc/code"
|
|
||||||
epb "google.golang.org/genproto/googleapis/rpc/errdetails"
|
|
||||||
spb "google.golang.org/genproto/googleapis/rpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// errEqual is essentially a copy of testutils.StatusErrEqual(), to avoid a
|
|
||||||
// cyclic dependency.
|
|
||||||
func errEqual(err1, err2 error) bool {
|
|
||||||
status1, ok := FromError(err1)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
status2, ok := FromError(err2)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return proto.Equal(status1.Proto(), status2.Proto())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorsWithSameParameters(t *testing.T) {
|
|
||||||
const description = "some description"
|
|
||||||
e1 := Errorf(codes.AlreadyExists, description)
|
|
||||||
e2 := Errorf(codes.AlreadyExists, description)
|
|
||||||
if e1 == e2 || !errEqual(e1, e2) {
|
|
||||||
t.Fatalf("Errors should be equivalent but unique - e1: %v, %v e2: %p, %v", e1.(*statusError), e1, e2.(*statusError), e2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromToProto(t *testing.T) {
|
|
||||||
s := &spb.Status{
|
|
||||||
Code: int32(codes.Internal),
|
|
||||||
Message: "test test test",
|
|
||||||
Details: []*apb.Any{{TypeUrl: "foo", Value: []byte{3, 2, 1}}},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := FromProto(s)
|
|
||||||
if got := err.Proto(); !proto.Equal(s, got) {
|
|
||||||
t.Fatalf("Expected errors to be identical - s: %v got: %v", s, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromNilProto(t *testing.T) {
|
|
||||||
tests := []*Status{nil, FromProto(nil)}
|
|
||||||
for _, s := range tests {
|
|
||||||
if c := s.Code(); c != codes.OK {
|
|
||||||
t.Errorf("s: %v - Expected s.Code() = OK; got %v", s, c)
|
|
||||||
}
|
|
||||||
if m := s.Message(); m != "" {
|
|
||||||
t.Errorf("s: %v - Expected s.Message() = \"\"; got %q", s, m)
|
|
||||||
}
|
|
||||||
if p := s.Proto(); p != nil {
|
|
||||||
t.Errorf("s: %v - Expected s.Proto() = nil; got %q", s, p)
|
|
||||||
}
|
|
||||||
if e := s.Err(); e != nil {
|
|
||||||
t.Errorf("s: %v - Expected s.Err() = nil; got %v", s, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestError(t *testing.T) {
|
|
||||||
err := Error(codes.Internal, "test description")
|
|
||||||
if got, want := err.Error(), "rpc error: code = Internal desc = test description"; got != want {
|
|
||||||
t.Fatalf("err.Error() = %q; want %q", got, want)
|
|
||||||
}
|
|
||||||
s, _ := FromError(err)
|
|
||||||
if got, want := s.Code(), codes.Internal; got != want {
|
|
||||||
t.Fatalf("err.Code() = %s; want %s", got, want)
|
|
||||||
}
|
|
||||||
if got, want := s.Message(), "test description"; got != want {
|
|
||||||
t.Fatalf("err.Message() = %s; want %s", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorOK(t *testing.T) {
|
|
||||||
err := Error(codes.OK, "foo")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error(codes.OK, _) = %p; want nil", err.(*statusError))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorProtoOK(t *testing.T) {
|
|
||||||
s := &spb.Status{Code: int32(codes.OK)}
|
|
||||||
if got := ErrorProto(s); got != nil {
|
|
||||||
t.Fatalf("ErrorProto(%v) = %v; want nil", s, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromError(t *testing.T) {
|
|
||||||
code, message := codes.Internal, "test description"
|
|
||||||
err := Error(code, message)
|
|
||||||
s, ok := FromError(err)
|
|
||||||
if !ok || s.Code() != code || s.Message() != message || s.Err() == nil {
|
|
||||||
t.Fatalf("FromError(%v) = %v, %v; want <Code()=%s, Message()=%q, Err()!=nil>, true", err, s, ok, code, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromErrorOK(t *testing.T) {
|
|
||||||
code, message := codes.OK, ""
|
|
||||||
s, ok := FromError(nil)
|
|
||||||
if !ok || s.Code() != code || s.Message() != message || s.Err() != nil {
|
|
||||||
t.Fatalf("FromError(nil) = %v, %v; want <Code()=%s, Message()=%q, Err=nil>, true", s, ok, code, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type customError struct {
|
|
||||||
Code codes.Code
|
|
||||||
Message string
|
|
||||||
Details []*apb.Any
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c customError) Error() string {
|
|
||||||
return fmt.Sprintf("rpc error: code = %s desc = %s", c.Code, c.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c customError) GRPCStatus() *Status {
|
|
||||||
return &Status{
|
|
||||||
s: &spb.Status{
|
|
||||||
Code: int32(c.Code),
|
|
||||||
Message: c.Message,
|
|
||||||
Details: c.Details,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromErrorImplementsInterface(t *testing.T) {
|
|
||||||
code, message := codes.Internal, "test description"
|
|
||||||
details := []*apb.Any{{
|
|
||||||
TypeUrl: "testUrl",
|
|
||||||
Value: []byte("testValue"),
|
|
||||||
}}
|
|
||||||
err := customError{
|
|
||||||
Code: code,
|
|
||||||
Message: message,
|
|
||||||
Details: details,
|
|
||||||
}
|
|
||||||
s, ok := FromError(err)
|
|
||||||
if !ok || s.Code() != code || s.Message() != message || s.Err() == nil {
|
|
||||||
t.Fatalf("FromError(%v) = %v, %v; want <Code()=%s, Message()=%q, Err()!=nil>, true", err, s, ok, code, message)
|
|
||||||
}
|
|
||||||
pd := s.Proto().GetDetails()
|
|
||||||
if len(pd) != 1 || !proto.Equal(pd[0], details[0]) {
|
|
||||||
t.Fatalf("s.Proto.GetDetails() = %v; want <Details()=%s>", pd, details)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromErrorUnknownError(t *testing.T) {
|
|
||||||
code, message := codes.Unknown, "unknown error"
|
|
||||||
err := errors.New("unknown error")
|
|
||||||
s, ok := FromError(err)
|
|
||||||
if ok || s.Code() != code || s.Message() != message {
|
|
||||||
t.Fatalf("FromError(%v) = %v, %v; want <Code()=%s, Message()=%q>, false", err, s, ok, code, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvertKnownError(t *testing.T) {
|
|
||||||
code, message := codes.Internal, "test description"
|
|
||||||
err := Error(code, message)
|
|
||||||
s := Convert(err)
|
|
||||||
if s.Code() != code || s.Message() != message {
|
|
||||||
t.Fatalf("Convert(%v) = %v; want <Code()=%s, Message()=%q>", err, s, code, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvertUnknownError(t *testing.T) {
|
|
||||||
code, message := codes.Unknown, "unknown error"
|
|
||||||
err := errors.New("unknown error")
|
|
||||||
s := Convert(err)
|
|
||||||
if s.Code() != code || s.Message() != message {
|
|
||||||
t.Fatalf("Convert(%v) = %v; want <Code()=%s, Message()=%q>", err, s, code, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStatus_ErrorDetails(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
code codes.Code
|
|
||||||
details []proto.Message
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
code: codes.NotFound,
|
|
||||||
details: nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: codes.NotFound,
|
|
||||||
details: []proto.Message{
|
|
||||||
&epb.ResourceInfo{
|
|
||||||
ResourceType: "book",
|
|
||||||
ResourceName: "projects/1234/books/5678",
|
|
||||||
Owner: "User",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: codes.Internal,
|
|
||||||
details: []proto.Message{
|
|
||||||
&epb.DebugInfo{
|
|
||||||
StackEntries: []string{
|
|
||||||
"first stack",
|
|
||||||
"second stack",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: codes.Unavailable,
|
|
||||||
details: []proto.Message{
|
|
||||||
&epb.RetryInfo{
|
|
||||||
RetryDelay: &dpb.Duration{Seconds: 60},
|
|
||||||
},
|
|
||||||
&epb.ResourceInfo{
|
|
||||||
ResourceType: "book",
|
|
||||||
ResourceName: "projects/1234/books/5678",
|
|
||||||
Owner: "User",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tests {
|
|
||||||
s, err := New(tc.code, "").WithDetails(tc.details...)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("(%v).WithDetails(%+v) failed: %v", str(s), tc.details, err)
|
|
||||||
}
|
|
||||||
details := s.Details()
|
|
||||||
for i := range details {
|
|
||||||
if !proto.Equal(details[i].(proto.Message), tc.details[i]) {
|
|
||||||
t.Fatalf("(%v).Details()[%d] = %+v, want %+v", str(s), i, details[i], tc.details[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStatus_WithDetails_Fail(t *testing.T) {
|
|
||||||
tests := []*Status{
|
|
||||||
nil,
|
|
||||||
FromProto(nil),
|
|
||||||
New(codes.OK, ""),
|
|
||||||
}
|
|
||||||
for _, s := range tests {
|
|
||||||
if s, err := s.WithDetails(); err == nil || s != nil {
|
|
||||||
t.Fatalf("(%v).WithDetails(%+v) = %v, %v; want nil, non-nil", str(s), []proto.Message{}, s, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStatus_ErrorDetails_Fail(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
s *Status
|
|
||||||
i []interface{}
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
FromProto(nil),
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
New(codes.OK, ""),
|
|
||||||
[]interface{}{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
FromProto(&spb.Status{
|
|
||||||
Code: int32(cpb.Code_CANCELLED),
|
|
||||||
Details: []*apb.Any{
|
|
||||||
{
|
|
||||||
TypeUrl: "",
|
|
||||||
Value: []byte{},
|
|
||||||
},
|
|
||||||
mustMarshalAny(&epb.ResourceInfo{
|
|
||||||
ResourceType: "book",
|
|
||||||
ResourceName: "projects/1234/books/5678",
|
|
||||||
Owner: "User",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
[]interface{}{
|
|
||||||
errors.New(`message type url "" is invalid`),
|
|
||||||
&epb.ResourceInfo{
|
|
||||||
ResourceType: "book",
|
|
||||||
ResourceName: "projects/1234/books/5678",
|
|
||||||
Owner: "User",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tests {
|
|
||||||
got := tc.s.Details()
|
|
||||||
if !reflect.DeepEqual(got, tc.i) {
|
|
||||||
t.Errorf("(%v).Details() = %+v, want %+v", str(tc.s), got, tc.i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func str(s *Status) string {
|
|
||||||
if s == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
if s.s == nil {
|
|
||||||
return "<Code=OK>"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("<Code=%v, Message=%q, Details=%+v>", codes.Code(s.s.GetCode()), s.s.GetMessage(), s.s.GetDetails())
|
|
||||||
}
|
|
||||||
|
|
||||||
// mustMarshalAny converts a protobuf message to an any.
|
|
||||||
func mustMarshalAny(msg proto.Message) *apb.Any {
|
|
||||||
any, err := ptypes.MarshalAny(msg)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("ptypes.MarshalAny(%+v) failed: %v", msg, err))
|
|
||||||
}
|
|
||||||
return any
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromContextError(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
in error
|
|
||||||
want *Status
|
|
||||||
}{
|
|
||||||
{in: nil, want: New(codes.OK, "")},
|
|
||||||
{in: context.DeadlineExceeded, want: New(codes.DeadlineExceeded, context.DeadlineExceeded.Error())},
|
|
||||||
{in: context.Canceled, want: New(codes.Canceled, context.Canceled.Error())},
|
|
||||||
{in: errors.New("other"), want: New(codes.Unknown, "other")},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
got := FromContextError(tc.in)
|
|
||||||
if got.Code() != tc.want.Code() || got.Message() != tc.want.Message() {
|
|
||||||
t.Errorf("FromContextError(%v) = %v; want %v", tc.in, got, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user