OSDN Git Service

OpenTween v2.4.2 リリース
[opentween/open-tween.git] / OpenTween.Tests / ShortUrlTest.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
15 // for more details.
16 //
17 // You should have received a copy of the GNU General public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 using System;
23 using System.Collections.Generic;
24 using System.Linq;
25 using System.Net;
26 using System.Net.Http;
27 using System.Text;
28 using System.Threading;
29 using System.Threading.Tasks;
30 using Xunit;
31 using Xunit.Extensions;
32
33 namespace OpenTween
34 {
35     public class ShortUrlTest
36     {
37         [Fact]
38         public async Task ExpandUrlAsync_Test()
39         {
40             var handler = new HttpMessageHandlerMock();
41             using (var http = new HttpClient(handler))
42             {
43                 var shortUrl = new ShortUrl(http);
44
45                 // https://t.co/hoge1 -> http://example.com/hoge2
46                 handler.Enqueue(x =>
47                 {
48                     Assert.Equal(HttpMethod.Head, x.Method);
49                     Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
50
51                     return this.CreateRedirectResponse("http://example.com/hoge2");
52                 });
53
54                 Assert.Equal(new Uri("http://example.com/hoge2"),
55                     await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
56
57                 Assert.Equal(0, handler.QueueCount);
58             }
59         }
60
61         [Fact]
62         public async Task ExpandUrlAsync_IrregularUrlTest()
63         {
64             var handler = new HttpMessageHandlerMock();
65             using (var http = new HttpClient(handler))
66             {
67                 var shortUrl = new ShortUrl(http);
68
69                 // https://www.flickr.com/photo.gne?short=hoge -> /photos/foo/11111/
70                 handler.Enqueue(x =>
71                 {
72                     Assert.Equal(HttpMethod.Head, x.Method);
73                     Assert.Equal(new Uri("https://www.flickr.com/photo.gne?short=hoge"), x.RequestUri);
74
75                     return this.CreateRedirectResponse("/photos/foo/11111/", UriKind.Relative);
76                 });
77
78                 Assert.Equal(new Uri("https://www.flickr.com/photos/foo/11111/"),
79                     await shortUrl.ExpandUrlAsync(new Uri("https://www.flickr.com/photo.gne?short=hoge")));
80
81                 Assert.Equal(0, handler.QueueCount);
82             }
83         }
84
85         [Fact]
86         public async Task ExpandUrlAsync_DisableExpandingTest()
87         {
88             var handler = new HttpMessageHandlerMock();
89             using (var http = new HttpClient(handler))
90             {
91                 var shortUrl = new ShortUrl(http);
92
93                 shortUrl.DisableExpanding = true;
94
95                 // https://t.co/hoge1 -> http://example.com/hoge2
96                 handler.Enqueue(x =>
97                 {
98                     // このリクエストは実行されないはず
99                     Assert.True(false);
100                     return this.CreateRedirectResponse("http://example.com/hoge2");
101                 });
102
103                 Assert.Equal(new Uri("https://t.co/hoge1"),
104                     await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
105
106                 Assert.Equal(1, handler.QueueCount);
107             }
108         }
109
110         [Fact]
111         public async Task ExpandUrlAsync_RecursiveTest()
112         {
113             var handler = new HttpMessageHandlerMock();
114             using (var http = new HttpClient(handler))
115             {
116                 var shortUrl = new ShortUrl(http);
117
118                 // https://t.co/hoge1 -> https://bit.ly/hoge2
119                 handler.Enqueue(x =>
120                 {
121                     Assert.Equal(HttpMethod.Head, x.Method);
122                     Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
123
124                     return this.CreateRedirectResponse("https://bit.ly/hoge2");
125                 });
126
127                 // https://bit.ly/hoge2 -> http://example.com/hoge3
128                 handler.Enqueue(x =>
129                 {
130                     Assert.Equal(HttpMethod.Head, x.Method);
131                     Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
132
133                     return this.CreateRedirectResponse("http://example.com/hoge3");
134                 });
135
136                 Assert.Equal(new Uri("http://example.com/hoge3"),
137                     await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
138
139                 Assert.Equal(0, handler.QueueCount);
140             }
141         }
142
143         [Fact]
144         public async Task ExpandUrlAsync_RecursiveLimitTest()
145         {
146             var handler = new HttpMessageHandlerMock();
147             using (var http = new HttpClient(handler))
148             {
149                 var shortUrl = new ShortUrl(http);
150
151                 // https://t.co/hoge1 -> https://bit.ly/hoge2
152                 handler.Enqueue(x =>
153                 {
154                     Assert.Equal(HttpMethod.Head, x.Method);
155                     Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
156
157                     return this.CreateRedirectResponse("https://bit.ly/hoge2");
158                 });
159
160                 // https://bit.ly/hoge2 -> https://tinyurl.com/hoge3
161                 handler.Enqueue(x =>
162                 {
163                     Assert.Equal(HttpMethod.Head, x.Method);
164                     Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
165
166                     return this.CreateRedirectResponse("https://tinyurl.com/hoge3");
167                 });
168
169                 // https://tinyurl.com/hoge3 -> http://example.com/hoge4
170                 handler.Enqueue(x =>
171                 {
172                     // このリクエストは実行されないはず
173                     Assert.True(false);
174                     return this.CreateRedirectResponse("http://example.com/hoge4");
175                 });
176
177                 Assert.Equal(new Uri("https://tinyurl.com/hoge3"),
178                     await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1"), redirectLimit: 2));
179
180                 Assert.Equal(1, handler.QueueCount);
181             }
182         }
183
184         [Fact]
185         public async Task ExpandUrlAsync_UpgradeToHttpsTest()
186         {
187             var handler = new HttpMessageHandlerMock();
188             using (var http = new HttpClient(handler))
189             {
190                 var shortUrl = new ShortUrl(http);
191
192                 // http://t.co/hoge -> http://example.com/hoge
193                 handler.Enqueue(x =>
194                 {
195                     // https:// に変換されてリクエストが送信される
196                     Assert.Equal(HttpMethod.Head, x.Method);
197                     Assert.Equal(new Uri("https://t.co/hoge"), x.RequestUri);
198
199                     return this.CreateRedirectResponse("http://example.com/hoge");
200                 });
201
202                 Assert.Equal(new Uri("http://example.com/hoge"),
203                     await shortUrl.ExpandUrlAsync(new Uri("http://t.co/hoge")));
204
205                 Assert.Equal(0, handler.QueueCount);
206             }
207         }
208
209         [Fact]
210         public async Task ExpandUrlAsync_InsecureDomainTest()
211         {
212             var handler = new HttpMessageHandlerMock();
213             using (var http = new HttpClient(handler))
214             {
215                 var shortUrl = new ShortUrl(http);
216
217                 // http://tinami.jp/hoge -> http://example.com/hoge
218                 handler.Enqueue(x =>
219                 {
220                     // HTTPS非対応のドメインは http:// のままリクエストが送信される
221                     Assert.Equal(HttpMethod.Head, x.Method);
222                     Assert.Equal(new Uri("http://tinami.jp/hoge"), x.RequestUri);
223
224                     return this.CreateRedirectResponse("http://example.com/hoge");
225                 });
226
227                 Assert.Equal(new Uri("http://example.com/hoge"),
228                     await shortUrl.ExpandUrlAsync(new Uri("http://tinami.jp/hoge")));
229
230                 Assert.Equal(0, handler.QueueCount);
231             }
232         }
233
234         [Fact]
235         public async Task ExpandUrlAsync_RelativeUriTest()
236         {
237             var handler = new HttpMessageHandlerMock();
238             using (var http = new HttpClient(handler))
239             {
240                 var shortUrl = new ShortUrl(http);
241
242                 handler.Enqueue(x =>
243                 {
244                     // このリクエストは実行されないはず
245                     Assert.True(false);
246                     return this.CreateRedirectResponse("");
247                 });
248
249                 // 相対 URI に対しては何も行わない
250                 Assert.Equal(new Uri("./foo/bar", UriKind.Relative),
251                     await shortUrl.ExpandUrlAsync(new Uri("./foo/bar", UriKind.Relative)));
252
253                 Assert.Equal(1, handler.QueueCount);
254             }
255         }
256
257         [Fact]
258         public async Task ExpandUrlAsync_RelativeRedirectTest()
259         {
260             var handler = new HttpMessageHandlerMock();
261             using (var http = new HttpClient(handler))
262             {
263                 var shortUrl = new ShortUrl(http);
264
265                 // Location に相対 URL を指定したリダイレクト (テストに使う URL は適当)
266                 // https://t.co/hogehoge -> /tetetete
267                 handler.Enqueue(x =>
268                 {
269                     Assert.Equal(HttpMethod.Head, x.Method);
270                     Assert.Equal(new Uri("https://t.co/hogehoge"), x.RequestUri);
271
272                     return this.CreateRedirectResponse("/tetetete", UriKind.Relative);
273                 });
274
275                 // https://t.co/tetetete -> http://example.com/tetetete
276                 handler.Enqueue(x =>
277                 {
278                     Assert.Equal(HttpMethod.Head, x.Method);
279                     Assert.Equal(new Uri("https://t.co/tetetete"), x.RequestUri);
280
281                     return this.CreateRedirectResponse("http://example.com/tetetete");
282                 });
283
284                 Assert.Equal(new Uri("http://example.com/tetetete"),
285                     await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hogehoge")));
286
287                 Assert.Equal(0, handler.QueueCount);
288             }
289         }
290
291         [Fact]
292         public async Task ExpandUrlAsync_String_Test()
293         {
294             var handler = new HttpMessageHandlerMock();
295             using (var http = new HttpClient(handler))
296             {
297                 var shortUrl = new ShortUrl(http);
298
299                 // https://t.co/hoge1 -> http://example.com/hoge2
300                 handler.Enqueue(x =>
301                 {
302                     Assert.Equal(HttpMethod.Head, x.Method);
303                     Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
304
305                     return this.CreateRedirectResponse("http://example.com/hoge2");
306                 });
307
308                 Assert.Equal("http://example.com/hoge2",
309                     await shortUrl.ExpandUrlAsync("https://t.co/hoge1"));
310
311                 Assert.Equal(0, handler.QueueCount);
312             }
313         }
314
315         [Fact]
316         public async Task ExpandUrlAsync_String_SchemeLessUrlTest()
317         {
318             var handler = new HttpMessageHandlerMock();
319             using (var http = new HttpClient(handler))
320             {
321                 var shortUrl = new ShortUrl(http);
322
323                 // https://t.co/hoge1 -> http://example.com/hoge2
324                 handler.Enqueue(x =>
325                 {
326                     Assert.Equal(HttpMethod.Head, x.Method);
327                     Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
328
329                     return this.CreateRedirectResponse("http://example.com/hoge2");
330                 });
331
332                 // スキームが省略されたURL
333                 Assert.Equal("http://example.com/hoge2",
334                     await shortUrl.ExpandUrlAsync("t.co/hoge1"));
335
336                 Assert.Equal(0, handler.QueueCount);
337             }
338         }
339
340         [Fact]
341         public async Task ExpandUrlAsync_String_InvalidUrlTest()
342         {
343             var handler = new HttpMessageHandlerMock();
344             using (var http = new HttpClient(handler))
345             {
346                 var shortUrl = new ShortUrl(http);
347
348                 handler.Enqueue(x =>
349                 {
350                     // リクエストは送信されないはず
351                     Assert.True(false);
352                     return this.CreateRedirectResponse("http://example.com/hoge2");
353                 });
354
355                 // 不正なURL
356                 Assert.Equal("..hogehoge..", await shortUrl.ExpandUrlAsync("..hogehoge.."));
357
358                 Assert.Equal(1, handler.QueueCount);
359             }
360         }
361
362         [Fact]
363         public async Task ExpandUrlAsync_HttpErrorTest()
364         {
365             var handler = new HttpMessageHandlerMock();
366             using (var http = new HttpClient(handler))
367             {
368                 var shortUrl = new ShortUrl(http);
369
370                 // https://t.co/hoge1 -> 503 Service Unavailable
371                 handler.Enqueue(x =>
372                 {
373                     return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
374                 });
375
376                 Assert.Equal(new Uri("https://t.co/hoge1"),
377                     await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
378
379                 Assert.Equal(0, handler.QueueCount);
380             }
381         }
382
383         [Fact]
384         public async Task ExpandUrlHtmlAsync_Test()
385         {
386             var handler = new HttpMessageHandlerMock();
387             using (var http = new HttpClient(handler))
388             {
389                 var shortUrl = new ShortUrl(http);
390
391                 // https://t.co/hoge1 -> http://example.com/hoge2
392                 handler.Enqueue(x =>
393                 {
394                     Assert.Equal(HttpMethod.Head, x.Method);
395                     Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
396
397                     return this.CreateRedirectResponse("http://example.com/hoge2");
398                 });
399
400                 Assert.Equal("<a href=\"http://example.com/hoge2\">hogehoge</a>",
401                     await shortUrl.ExpandUrlHtmlAsync("<a href=\"https://t.co/hoge1\">hogehoge</a>"));
402
403                 Assert.Equal(0, handler.QueueCount);
404             }
405         }
406
407         [Fact]
408         public async Task ExpandUrlHtmlAsync_RelativeUriTest()
409         {
410             var handler = new HttpMessageHandlerMock();
411             using (var http = new HttpClient(handler))
412             {
413                 var shortUrl = new ShortUrl(http);
414
415                 handler.Enqueue(x =>
416                 {
417                     // リクエストは送信されないはず
418                     Assert.True(false);
419                     return this.CreateRedirectResponse("http://example.com/hoge");
420                 });
421
422                 Assert.Equal("<a href=\"./hoge\">hogehoge</a>",
423                     await shortUrl.ExpandUrlHtmlAsync("<a href=\"./hoge\">hogehoge</a>"));
424
425                 Assert.Equal(1, handler.QueueCount);
426             }
427         }
428
429         private HttpResponseMessage CreateRedirectResponse(string uriStr)
430             => this.CreateRedirectResponse(uriStr, UriKind.Absolute);
431
432         private HttpResponseMessage CreateRedirectResponse(string uriStr, UriKind uriKind)
433         {
434             var response = new HttpResponseMessage(HttpStatusCode.TemporaryRedirect);
435             response.Headers.Location = new Uri(uriStr, uriKind);
436             return response;
437         }
438
439         [Fact]
440         public async Task ShortenUrlAsync_TinyUrlTest()
441         {
442             var handler = new HttpMessageHandlerMock();
443             using (var http = new HttpClient(handler))
444             {
445                 var shortUrl = new ShortUrl(http);
446
447                 handler.Enqueue(async x =>
448                 {
449                     Assert.Equal(HttpMethod.Post, x.Method);
450                     Assert.Equal(new Uri("https://tinyurl.com/api-create.php"), x.RequestUri);
451                     Assert.Equal("url=http%3A%2F%2Fexample.com%2Fhogehogehoge", await x.Content.ReadAsStringAsync());
452
453                     return new HttpResponseMessage(HttpStatusCode.OK)
454                     {
455                         Content = new ByteArrayContent(Encoding.UTF8.GetBytes("http://tinyurl.com/hoge")),
456                     };
457                 });
458
459                 Assert.Equal(new Uri("https://tinyurl.com/hoge"),
460                     await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.TinyUrl, new Uri("http://example.com/hogehogehoge")));
461
462                 Assert.Equal(0, handler.QueueCount);
463             }
464         }
465
466         [Fact]
467         public async Task ShortenUrlAsync_UxnuUrlTest()
468         {
469             var handler = new HttpMessageHandlerMock();
470             using (var http = new HttpClient(handler))
471             {
472                 var shortUrl = new ShortUrl(http);
473
474                 handler.Enqueue(x =>
475                 {
476                     Assert.Equal(HttpMethod.Get, x.Method);
477                     Assert.Equal("https://ux.nu/api/short?format=plain&url=http:%2F%2Fexample.com%2Fhogehoge",
478                         x.RequestUri.AbsoluteUri);
479
480                     return new HttpResponseMessage(HttpStatusCode.OK)
481                     {
482                         Content = new ByteArrayContent(Encoding.UTF8.GetBytes("https://ux.nu/hoge")),
483                     };
484                 });
485
486                 Assert.Equal(new Uri("https://ux.nu/hoge"),
487                     await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.Uxnu, new Uri("http://example.com/hogehoge")));
488
489                 Assert.Equal(0, handler.QueueCount);
490             }
491         }
492     }
493 }