github.com/daaku/docker@v1.5.0/registry/v2/errors_test.go (about)

     1  package v2
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  	"testing"
     7  )
     8  
     9  // TestErrorCodes ensures that error code format, mappings and
    10  // marshaling/unmarshaling. round trips are stable.
    11  func TestErrorCodes(t *testing.T) {
    12  	for _, desc := range ErrorDescriptors {
    13  		if desc.Code.String() != desc.Value {
    14  			t.Fatalf("error code string incorrect: %q != %q", desc.Code.String(), desc.Value)
    15  		}
    16  
    17  		if desc.Code.Message() != desc.Message {
    18  			t.Fatalf("incorrect message for error code %v: %q != %q", desc.Code, desc.Code.Message(), desc.Message)
    19  		}
    20  
    21  		// Serialize the error code using the json library to ensure that we
    22  		// get a string and it works round trip.
    23  		p, err := json.Marshal(desc.Code)
    24  
    25  		if err != nil {
    26  			t.Fatalf("error marshaling error code %v: %v", desc.Code, err)
    27  		}
    28  
    29  		if len(p) <= 0 {
    30  			t.Fatalf("expected content in marshaled before for error code %v", desc.Code)
    31  		}
    32  
    33  		// First, unmarshal to interface and ensure we have a string.
    34  		var ecUnspecified interface{}
    35  		if err := json.Unmarshal(p, &ecUnspecified); err != nil {
    36  			t.Fatalf("error unmarshaling error code %v: %v", desc.Code, err)
    37  		}
    38  
    39  		if _, ok := ecUnspecified.(string); !ok {
    40  			t.Fatalf("expected a string for error code %v on unmarshal got a %T", desc.Code, ecUnspecified)
    41  		}
    42  
    43  		// Now, unmarshal with the error code type and ensure they are equal
    44  		var ecUnmarshaled ErrorCode
    45  		if err := json.Unmarshal(p, &ecUnmarshaled); err != nil {
    46  			t.Fatalf("error unmarshaling error code %v: %v", desc.Code, err)
    47  		}
    48  
    49  		if ecUnmarshaled != desc.Code {
    50  			t.Fatalf("unexpected error code during error code marshal/unmarshal: %v != %v", ecUnmarshaled, desc.Code)
    51  		}
    52  	}
    53  }
    54  
    55  // TestErrorsManagement does a quick check of the Errors type to ensure that
    56  // members are properly pushed and marshaled.
    57  func TestErrorsManagement(t *testing.T) {
    58  	var errs Errors
    59  
    60  	errs.Push(ErrorCodeDigestInvalid)
    61  	errs.Push(ErrorCodeBlobUnknown,
    62  		map[string]string{"digest": "sometestblobsumdoesntmatter"})
    63  
    64  	p, err := json.Marshal(errs)
    65  
    66  	if err != nil {
    67  		t.Fatalf("error marashaling errors: %v", err)
    68  	}
    69  
    70  	expectedJSON := "{\"errors\":[{\"code\":\"DIGEST_INVALID\",\"message\":\"provided digest did not match uploaded content\"},{\"code\":\"BLOB_UNKNOWN\",\"message\":\"blob unknown to registry\",\"detail\":{\"digest\":\"sometestblobsumdoesntmatter\"}}]}"
    71  
    72  	if string(p) != expectedJSON {
    73  		t.Fatalf("unexpected json: %q != %q", string(p), expectedJSON)
    74  	}
    75  
    76  	errs.Clear()
    77  	errs.Push(ErrorCodeUnknown)
    78  	expectedJSON = "{\"errors\":[{\"code\":\"UNKNOWN\",\"message\":\"unknown error\"}]}"
    79  	p, err = json.Marshal(errs)
    80  
    81  	if err != nil {
    82  		t.Fatalf("error marashaling errors: %v", err)
    83  	}
    84  
    85  	if string(p) != expectedJSON {
    86  		t.Fatalf("unexpected json: %q != %q", string(p), expectedJSON)
    87  	}
    88  }
    89  
    90  // TestMarshalUnmarshal ensures that api errors can round trip through json
    91  // without losing information.
    92  func TestMarshalUnmarshal(t *testing.T) {
    93  
    94  	var errors Errors
    95  
    96  	for _, testcase := range []struct {
    97  		description string
    98  		err         Error
    99  	}{
   100  		{
   101  			description: "unknown error",
   102  			err: Error{
   103  
   104  				Code:    ErrorCodeUnknown,
   105  				Message: ErrorCodeUnknown.Descriptor().Message,
   106  			},
   107  		},
   108  		{
   109  			description: "unknown manifest",
   110  			err: Error{
   111  				Code:    ErrorCodeManifestUnknown,
   112  				Message: ErrorCodeManifestUnknown.Descriptor().Message,
   113  			},
   114  		},
   115  		{
   116  			description: "unknown manifest",
   117  			err: Error{
   118  				Code:    ErrorCodeBlobUnknown,
   119  				Message: ErrorCodeBlobUnknown.Descriptor().Message,
   120  				Detail:  map[string]interface{}{"digest": "asdfqwerqwerqwerqwer"},
   121  			},
   122  		},
   123  	} {
   124  		fatalf := func(format string, args ...interface{}) {
   125  			t.Fatalf(testcase.description+": "+format, args...)
   126  		}
   127  
   128  		unexpectedErr := func(err error) {
   129  			fatalf("unexpected error: %v", err)
   130  		}
   131  
   132  		p, err := json.Marshal(testcase.err)
   133  		if err != nil {
   134  			unexpectedErr(err)
   135  		}
   136  
   137  		var unmarshaled Error
   138  		if err := json.Unmarshal(p, &unmarshaled); err != nil {
   139  			unexpectedErr(err)
   140  		}
   141  
   142  		if !reflect.DeepEqual(unmarshaled, testcase.err) {
   143  			fatalf("errors not equal after round trip: %#v != %#v", unmarshaled, testcase.err)
   144  		}
   145  
   146  		// Roll everything up into an error response envelope.
   147  		errors.PushErr(testcase.err)
   148  	}
   149  
   150  	p, err := json.Marshal(errors)
   151  	if err != nil {
   152  		t.Fatalf("unexpected error marshaling error envelope: %v", err)
   153  	}
   154  
   155  	var unmarshaled Errors
   156  	if err := json.Unmarshal(p, &unmarshaled); err != nil {
   157  		t.Fatalf("unexpected error unmarshaling error envelope: %v", err)
   158  	}
   159  
   160  	if !reflect.DeepEqual(unmarshaled, errors) {
   161  		t.Fatalf("errors not equal after round trip: %#v != %#v", unmarshaled, errors)
   162  	}
   163  }