github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/api/errcode/errors_test.go (about) 1 package errcode 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "reflect" 7 "strings" 8 "testing" 9 ) 10 11 // TestErrorsManagement does a quick check of the Errors type to ensure that 12 // members are properly pushed and marshaled. 13 var ErrorCodeTest1 = Register("test.errors", ErrorDescriptor{ 14 Value: "TEST1", 15 Message: "test error 1", 16 Description: `Just a test message #1.`, 17 HTTPStatusCode: http.StatusInternalServerError, 18 }) 19 20 var ErrorCodeTest2 = Register("test.errors", ErrorDescriptor{ 21 Value: "TEST2", 22 Message: "test error 2", 23 Description: `Just a test message #2.`, 24 HTTPStatusCode: http.StatusNotFound, 25 }) 26 27 var ErrorCodeTest3 = Register("test.errors", ErrorDescriptor{ 28 Value: "TEST3", 29 Message: "Sorry %q isn't valid", 30 Description: `Just a test message #3.`, 31 HTTPStatusCode: http.StatusNotFound, 32 }) 33 34 // TestErrorCodes ensures that error code format, mappings and 35 // marshaling/unmarshaling. round trips are stable. 36 func TestErrorCodes(t *testing.T) { 37 if len(errorCodeToDescriptors) == 0 { 38 t.Fatal("errors aren't loaded!") 39 } 40 41 for ec, desc := range errorCodeToDescriptors { 42 if ec != desc.Code { 43 t.Fatalf("error code in descriptor isn't correct, %q != %q", ec, desc.Code) 44 } 45 46 if idToDescriptors[desc.Value].Code != ec { 47 t.Fatalf("error code in idToDesc isn't correct, %q != %q", idToDescriptors[desc.Value].Code, ec) 48 } 49 50 if ec.Message() != desc.Message { 51 t.Fatalf("ec.Message doesn't mtach desc.Message: %q != %q", ec.Message(), desc.Message) 52 } 53 54 // Test (de)serializing the ErrorCode 55 p, err := json.Marshal(ec) 56 if err != nil { 57 t.Fatalf("couldn't marshal ec %v: %v", ec, err) 58 } 59 60 if len(p) <= 0 { 61 t.Fatalf("expected content in marshaled before for error code %v", ec) 62 } 63 64 // First, unmarshal to interface and ensure we have a string. 65 var ecUnspecified interface{} 66 if err := json.Unmarshal(p, &ecUnspecified); err != nil { 67 t.Fatalf("error unmarshaling error code %v: %v", ec, err) 68 } 69 70 if _, ok := ecUnspecified.(string); !ok { 71 t.Fatalf("expected a string for error code %v on unmarshal got a %T", ec, ecUnspecified) 72 } 73 74 // Now, unmarshal with the error code type and ensure they are equal 75 var ecUnmarshaled ErrorCode 76 if err := json.Unmarshal(p, &ecUnmarshaled); err != nil { 77 t.Fatalf("error unmarshaling error code %v: %v", ec, err) 78 } 79 80 if ecUnmarshaled != ec { 81 t.Fatalf("unexpected error code during error code marshal/unmarshal: %v != %v", ecUnmarshaled, ec) 82 } 83 84 expectedErrorString := strings.ToLower(strings.Replace(ec.Descriptor().Value, "_", " ", -1)) 85 if ec.Error() != expectedErrorString { 86 t.Fatalf("unexpected return from %v.Error(): %q != %q", ec, ec.Error(), expectedErrorString) 87 } 88 } 89 90 } 91 92 func TestErrorsManagement(t *testing.T) { 93 var errs Errors 94 95 errs = append(errs, ErrorCodeTest1) 96 errs = append(errs, ErrorCodeTest2.WithDetail( 97 map[string]interface{}{"digest": "sometestblobsumdoesntmatter"})) 98 errs = append(errs, ErrorCodeTest3.WithArgs("BOOGIE")) 99 errs = append(errs, ErrorCodeTest3.WithArgs("BOOGIE").WithDetail("data")) 100 101 p, err := json.Marshal(errs) 102 103 if err != nil { 104 t.Fatalf("error marashaling errors: %v", err) 105 } 106 107 expectedJSON := `{"errors":[` + 108 `{"code":"TEST1","message":"test error 1"},` + 109 `{"code":"TEST2","message":"test error 2","detail":{"digest":"sometestblobsumdoesntmatter"}},` + 110 `{"code":"TEST3","message":"Sorry \"BOOGIE\" isn't valid"},` + 111 `{"code":"TEST3","message":"Sorry \"BOOGIE\" isn't valid","detail":"data"}` + 112 `]}` 113 114 if string(p) != expectedJSON { 115 t.Fatalf("unexpected json:\ngot:\n%q\n\nexpected:\n%q", string(p), expectedJSON) 116 } 117 118 // Now test the reverse 119 var unmarshaled Errors 120 if err := json.Unmarshal(p, &unmarshaled); err != nil { 121 t.Fatalf("unexpected error unmarshaling error envelope: %v", err) 122 } 123 124 if !reflect.DeepEqual(unmarshaled, errs) { 125 t.Fatalf("errors not equal after round trip:\nunmarshaled:\n%#v\n\nerrs:\n%#v", unmarshaled, errs) 126 } 127 128 // Test the arg substitution stuff 129 e1 := unmarshaled[3].(Error) 130 exp1 := `Sorry "BOOGIE" isn't valid` 131 if e1.Message != exp1 { 132 t.Fatalf("Wrong msg, got:\n%q\n\nexpected:\n%q", e1.Message, exp1) 133 } 134 135 exp1 = "test3: " + exp1 136 if e1.Error() != exp1 { 137 t.Fatalf("Error() didn't return the right string, got:%s\nexpected:%s", e1.Error(), exp1) 138 } 139 140 // Test again with a single value this time 141 errs = Errors{ErrorCodeUnknown} 142 expectedJSON = "{\"errors\":[{\"code\":\"UNKNOWN\",\"message\":\"unknown error\"}]}" 143 p, err = json.Marshal(errs) 144 145 if err != nil { 146 t.Fatalf("error marashaling errors: %v", err) 147 } 148 149 if string(p) != expectedJSON { 150 t.Fatalf("unexpected json: %q != %q", string(p), expectedJSON) 151 } 152 153 // Now test the reverse 154 unmarshaled = nil 155 if err := json.Unmarshal(p, &unmarshaled); err != nil { 156 t.Fatalf("unexpected error unmarshaling error envelope: %v", err) 157 } 158 159 if !reflect.DeepEqual(unmarshaled, errs) { 160 t.Fatalf("errors not equal after round trip:\nunmarshaled:\n%#v\n\nerrs:\n%#v", unmarshaled, errs) 161 } 162 163 // Verify that calling WithArgs() more than once does the right thing. 164 // Meaning creates a new Error and uses the ErrorCode Message 165 e1 = ErrorCodeTest3.WithArgs("test1") 166 e2 := e1.WithArgs("test2") 167 if &e1 == &e2 { 168 t.Fatalf("args: e2 and e1 should not be the same, but they are") 169 } 170 if e2.Message != `Sorry "test2" isn't valid` { 171 t.Fatalf("e2 had wrong message: %q", e2.Message) 172 } 173 174 // Verify that calling WithDetail() more than once does the right thing. 175 // Meaning creates a new Error and overwrites the old detail field 176 e1 = ErrorCodeTest3.WithDetail("stuff1") 177 e2 = e1.WithDetail("stuff2") 178 if &e1 == &e2 { 179 t.Fatalf("detail: e2 and e1 should not be the same, but they are") 180 } 181 if e2.Detail != `stuff2` { 182 t.Fatalf("e2 had wrong detail: %q", e2.Detail) 183 } 184 185 }