44package mail
55
66import (
7- "errors"
8- "io"
9- "net/http"
10- "net/http/httptest"
11- "strings"
127 "testing"
13-
14- "github.com/larksuite/cli/errs"
158)
169
17- func TestDownloadSignatureImageRejectsInvalidURLs (t * testing.T ) {
18- rt := newDownloadRuntime (t , & http.Client {})
19-
20- cases := []struct {
21- name string
22- url string
23- }{
24- {name : "invalid" , url : "https://[::1" },
25- {name : "http" , url : "http://example.com/sig.png" },
26- {name : "no host" , url : "https:///sig.png" },
27- }
28-
29- for _ , tc := range cases {
30- t .Run (tc .name , func (t * testing.T ) {
31- _ , _ , err := downloadSignatureImage (rt , tc .url , "sig.png" )
32- var internalErr * errs.InternalError
33- if ! errors .As (err , & internalErr ) {
34- t .Fatalf ("expected internal error, got %T (%v)" , err , err )
35- }
36- p , ok := errs .ProblemOf (err )
37- if ! ok {
38- t .Fatalf ("expected typed problem, got %T" , err )
39- }
40- if p .Subtype != errs .SubtypeInvalidResponse {
41- t .Fatalf ("subtype = %q, want %q" , p .Subtype , errs .SubtypeInvalidResponse )
42- }
43- })
44- }
45- }
46-
47- func TestDownloadSignatureImageHTTPErrorClassification (t * testing.T ) {
48- for _ , tc := range []struct {
49- name string
50- statusCode int
51- wantType any
52- wantSub errs.Subtype
53- retryable bool
54- }{
55- {
56- name : "server" ,
57- statusCode : http .StatusInternalServerError ,
58- wantType : (* errs .NetworkError )(nil ),
59- wantSub : errs .SubtypeNetworkServer ,
60- retryable : true ,
61- },
62- {
63- name : "not found" ,
64- statusCode : http .StatusNotFound ,
65- wantType : (* errs .APIError )(nil ),
66- wantSub : errs .SubtypeNotFound ,
67- },
68- } {
69- t .Run (tc .name , func (t * testing.T ) {
70- srv := httptest .NewTLSServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
71- http .Error (w , "download failed" , tc .statusCode )
72- }))
73- t .Cleanup (srv .Close )
74- rt := newDownloadRuntime (t , srv .Client ())
75-
76- _ , _ , err := downloadSignatureImage (rt , srv .URL + "/sig.png" , "sig.png" )
77- switch tc .wantType .(type ) {
78- case * errs.NetworkError :
79- var networkErr * errs.NetworkError
80- if ! errors .As (err , & networkErr ) {
81- t .Fatalf ("expected network error, got %T (%v)" , err , err )
82- }
83- case * errs.APIError :
84- var apiErr * errs.APIError
85- if ! errors .As (err , & apiErr ) {
86- t .Fatalf ("expected API error, got %T (%v)" , err , err )
87- }
88- }
89- p , ok := errs .ProblemOf (err )
90- if ! ok {
91- t .Fatalf ("expected typed problem, got %T" , err )
92- }
93- if p .Code != tc .statusCode {
94- t .Fatalf ("code = %d, want %d" , p .Code , tc .statusCode )
95- }
96- if p .Subtype != tc .wantSub {
97- t .Fatalf ("subtype = %q, want %q" , p .Subtype , tc .wantSub )
98- }
99- if p .Retryable != tc .retryable {
100- t .Fatalf ("retryable = %v, want %v" , p .Retryable , tc .retryable )
101- }
102- })
103- }
104- }
105-
106- func TestDownloadSignatureImageReadAndSizeErrors (t * testing.T ) {
107- readErr := errors .New ("socket closed" )
108- rt := newDownloadRuntime (t , & http.Client {
109- Transport : signatureRoundTripper (func (req * http.Request ) (* http.Response , error ) {
110- return & http.Response {
111- StatusCode : http .StatusOK ,
112- Header : make (http.Header ),
113- Body : signatureErrorBody {err : readErr },
114- Request : req ,
115- }, nil
116- }),
117- })
118-
119- _ , _ , err := downloadSignatureImage (rt , "https://example.com/sig.png" , "sig.png" )
120- var networkErr * errs.NetworkError
121- if ! errors .As (err , & networkErr ) {
122- t .Fatalf ("expected network error, got %T (%v)" , err , err )
123- }
124- if ! errors .Is (err , readErr ) {
125- t .Fatalf ("read cause not preserved: %v" , err )
126- }
127-
128- rt = newDownloadRuntime (t , & http.Client {
129- Transport : signatureRoundTripper (func (req * http.Request ) (* http.Response , error ) {
130- return & http.Response {
131- StatusCode : http .StatusOK ,
132- Header : make (http.Header ),
133- Body : & bodyFileTestFile {remaining : 10 * 1024 * 1024 + 1 },
134- Request : req ,
135- }, nil
136- }),
137- })
138-
139- _ , _ , err = downloadSignatureImage (rt , "https://example.com/huge.png" , "huge.png" )
140- var validationErr * errs.ValidationError
141- if ! errors .As (err , & validationErr ) {
142- t .Fatalf ("expected validation error, got %T (%v)" , err , err )
143- }
144- p , ok := errs .ProblemOf (err )
145- if ! ok {
146- t .Fatalf ("expected typed problem, got %T" , err )
147- }
148- if p .Subtype != errs .SubtypeFailedPrecondition {
149- t .Fatalf ("subtype = %q, want %q" , p .Subtype , errs .SubtypeFailedPrecondition )
150- }
151- }
152-
153- func TestDownloadSignatureImageSuccessUsesFilenameContentType (t * testing.T ) {
154- rt := newDownloadRuntime (t , & http.Client {
155- Transport : signatureRoundTripper (func (req * http.Request ) (* http.Response , error ) {
156- return & http.Response {
157- StatusCode : http .StatusOK ,
158- Header : make (http.Header ),
159- Body : io .NopCloser (strings .NewReader ("gif-data" )),
160- Request : req ,
161- }, nil
162- }),
163- })
164-
165- data , contentType , err := downloadSignatureImage (rt , "https://example.com/sig.gif" , "sig.gif" )
166- if err != nil {
167- t .Fatalf ("downloadSignatureImage failed: %v" , err )
168- }
169- if string (data ) != "gif-data" {
170- t .Fatalf ("data = %q" , string (data ))
171- }
172- if contentType != "image/gif" {
173- t .Fatalf ("content type = %q, want image/gif" , contentType )
174- }
175- }
176-
17710func TestValidateNoSignatureConflictTypedError (t * testing.T ) {
17811 err := validateNoSignatureConflict (true , "sig_123" )
17912 if err == nil {
@@ -193,21 +26,3 @@ func TestValidateNoSignatureConflictNoError(t *testing.T) {
19326 t .Fatalf ("expected no error when signatureID empty, got %v" , err )
19427 }
19528}
196-
197- type signatureRoundTripper func (* http.Request ) (* http.Response , error )
198-
199- func (rt signatureRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
200- return rt (req )
201- }
202-
203- type signatureErrorBody struct {
204- err error
205- }
206-
207- func (b signatureErrorBody ) Read ([]byte ) (int , error ) {
208- return 0 , b .err
209- }
210-
211- func (b signatureErrorBody ) Close () error {
212- return nil
213- }
0 commit comments